xref: /OK3568_Linux_fs/u-boot/arch/arm/cpu/armv7/cache_v7_asm.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/*
2*4882a593Smuzhiyun * SPDX-License-Identifier:	GPL-2.0+
3*4882a593Smuzhiyun */
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun#include <config.h>
6*4882a593Smuzhiyun#include <linux/linkage.h>
7*4882a593Smuzhiyun#include <linux/sizes.h>
8*4882a593Smuzhiyun#include <asm/system.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
11*4882a593Smuzhiyun#define ARM(x...)
12*4882a593Smuzhiyun#define THUMB(x...)	x
13*4882a593Smuzhiyun#else
14*4882a593Smuzhiyun#define ARM(x...)	x
15*4882a593Smuzhiyun#define THUMB(x...)
16*4882a593Smuzhiyun#endif
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun/*
19*4882a593Smuzhiyun *	v7_flush_dcache_all()
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun *	Flush the whole D-cache.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun *	Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
26*4882a593Smuzhiyun */
27*4882a593SmuzhiyunENTRY(__v7_flush_dcache_all)
28*4882a593Smuzhiyun	dmb					@ ensure ordering with previous memory accesses
29*4882a593Smuzhiyun	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
30*4882a593Smuzhiyun	mov	r3, r0, lsr #23			@ move LoC into position
31*4882a593Smuzhiyun	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
32*4882a593Smuzhiyun	beq	finished			@ if loc is 0, then no need to clean
33*4882a593Smuzhiyunstart_flush_levels:
34*4882a593Smuzhiyun	mov	r10, #0				@ start clean at cache level 0
35*4882a593Smuzhiyunflush_levels:
36*4882a593Smuzhiyun	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
37*4882a593Smuzhiyun	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
38*4882a593Smuzhiyun	and	r1, r1, #7			@ mask of the bits for current cache only
39*4882a593Smuzhiyun	cmp	r1, #2				@ see what cache we have at this level
40*4882a593Smuzhiyun	blt	skip				@ skip if no cache, or just i-cache
41*4882a593Smuzhiyun	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
42*4882a593Smuzhiyun	isb					@ isb to sych the new cssr&csidr
43*4882a593Smuzhiyun	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
44*4882a593Smuzhiyun	and	r2, r1, #7			@ extract the length of the cache lines
45*4882a593Smuzhiyun	add	r2, r2, #4			@ add 4 (line length offset)
46*4882a593Smuzhiyun	movw	r4, #0x3ff
47*4882a593Smuzhiyun	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
48*4882a593Smuzhiyun	clz	r5, r4				@ find bit position of way size increment
49*4882a593Smuzhiyun	movw	r7, #0x7fff
50*4882a593Smuzhiyun	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
51*4882a593Smuzhiyunloop1:
52*4882a593Smuzhiyun	mov	r9, r7				@ create working copy of max index
53*4882a593Smuzhiyunloop2:
54*4882a593Smuzhiyun ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
55*4882a593Smuzhiyun THUMB(	lsl	r6, r4, r5		)
56*4882a593Smuzhiyun THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
57*4882a593Smuzhiyun ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
58*4882a593Smuzhiyun THUMB(	lsl	r6, r9, r2		)
59*4882a593Smuzhiyun THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
60*4882a593Smuzhiyun	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
61*4882a593Smuzhiyun	subs	r9, r9, #1			@ decrement the index
62*4882a593Smuzhiyun	bge	loop2
63*4882a593Smuzhiyun	subs	r4, r4, #1			@ decrement the way
64*4882a593Smuzhiyun	bge	loop1
65*4882a593Smuzhiyunskip:
66*4882a593Smuzhiyun	add	r10, r10, #2			@ increment cache number
67*4882a593Smuzhiyun	cmp	r3, r10
68*4882a593Smuzhiyun	bgt	flush_levels
69*4882a593Smuzhiyunfinished:
70*4882a593Smuzhiyun	mov	r10, #0				@ swith back to cache level 0
71*4882a593Smuzhiyun	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
72*4882a593Smuzhiyun	dsb	st
73*4882a593Smuzhiyun	isb
74*4882a593Smuzhiyun	bx	lr
75*4882a593SmuzhiyunENDPROC(__v7_flush_dcache_all)
76*4882a593Smuzhiyun
77*4882a593SmuzhiyunENTRY(v7_flush_dcache_all)
78*4882a593Smuzhiyun ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
79*4882a593Smuzhiyun THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
80*4882a593Smuzhiyun	bl	__v7_flush_dcache_all
81*4882a593Smuzhiyun ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
82*4882a593Smuzhiyun THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
83*4882a593Smuzhiyun	bx	lr
84*4882a593SmuzhiyunENDPROC(v7_flush_dcache_all)
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun/*
87*4882a593Smuzhiyun *	v7_invalidate_dcache_all()
88*4882a593Smuzhiyun *
89*4882a593Smuzhiyun *	Invalidate the whole D-cache.
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun *	Note: copied from __v7_flush_dcache_all above with
94*4882a593Smuzhiyun *	mcr     p15, 0, r11, c7, c14, 2
95*4882a593Smuzhiyun *	Replaced with:
96*4882a593Smuzhiyun *	mcr     p15, 0, r11, c7, c6, 2
97*4882a593Smuzhiyun */
98*4882a593SmuzhiyunENTRY(__v7_invalidate_dcache_all)
99*4882a593Smuzhiyun	dmb					@ ensure ordering with previous memory accesses
100*4882a593Smuzhiyun	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
101*4882a593Smuzhiyun	mov	r3, r0, lsr #23			@ move LoC into position
102*4882a593Smuzhiyun	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
103*4882a593Smuzhiyun	beq	inval_finished			@ if loc is 0, then no need to clean
104*4882a593Smuzhiyun	mov	r10, #0				@ start clean at cache level 0
105*4882a593Smuzhiyuninval_levels:
106*4882a593Smuzhiyun	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
107*4882a593Smuzhiyun	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
108*4882a593Smuzhiyun	and	r1, r1, #7			@ mask of the bits for current cache only
109*4882a593Smuzhiyun	cmp	r1, #2				@ see what cache we have at this level
110*4882a593Smuzhiyun	blt	inval_skip			@ skip if no cache, or just i-cache
111*4882a593Smuzhiyun	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
112*4882a593Smuzhiyun	isb					@ isb to sych the new cssr&csidr
113*4882a593Smuzhiyun	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
114*4882a593Smuzhiyun	and	r2, r1, #7			@ extract the length of the cache lines
115*4882a593Smuzhiyun	add	r2, r2, #4			@ add 4 (line length offset)
116*4882a593Smuzhiyun	movw	r4, #0x3ff
117*4882a593Smuzhiyun	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
118*4882a593Smuzhiyun	clz	r5, r4				@ find bit position of way size increment
119*4882a593Smuzhiyun	movw	r7, #0x7fff
120*4882a593Smuzhiyun	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
121*4882a593Smuzhiyuninval_loop1:
122*4882a593Smuzhiyun	mov	r9, r7				@ create working copy of max index
123*4882a593Smuzhiyuninval_loop2:
124*4882a593Smuzhiyun ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
125*4882a593Smuzhiyun THUMB(	lsl	r6, r4, r5		)
126*4882a593Smuzhiyun THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
127*4882a593Smuzhiyun ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
128*4882a593Smuzhiyun THUMB(	lsl	r6, r9, r2		)
129*4882a593Smuzhiyun THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
130*4882a593Smuzhiyun	mcr	p15, 0, r11, c7, c6, 2		@ invalidate by set/way
131*4882a593Smuzhiyun	subs	r9, r9, #1			@ decrement the index
132*4882a593Smuzhiyun	bge	inval_loop2
133*4882a593Smuzhiyun	subs	r4, r4, #1			@ decrement the way
134*4882a593Smuzhiyun	bge	inval_loop1
135*4882a593Smuzhiyuninval_skip:
136*4882a593Smuzhiyun	add	r10, r10, #2			@ increment cache number
137*4882a593Smuzhiyun	cmp	r3, r10
138*4882a593Smuzhiyun	bgt	inval_levels
139*4882a593Smuzhiyuninval_finished:
140*4882a593Smuzhiyun	mov	r10, #0				@ swith back to cache level 0
141*4882a593Smuzhiyun	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
142*4882a593Smuzhiyun	dsb	st
143*4882a593Smuzhiyun	isb
144*4882a593Smuzhiyun	bx	lr
145*4882a593SmuzhiyunENDPROC(__v7_invalidate_dcache_all)
146*4882a593Smuzhiyun
147*4882a593SmuzhiyunENTRY(v7_invalidate_dcache_all)
148*4882a593Smuzhiyun ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
149*4882a593Smuzhiyun THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
150*4882a593Smuzhiyun	bl	__v7_invalidate_dcache_all
151*4882a593Smuzhiyun ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
152*4882a593Smuzhiyun THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
153*4882a593Smuzhiyun	bx	lr
154*4882a593SmuzhiyunENDPROC(v7_invalidate_dcache_all)
155