Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / mips / cpu / mips32 / cache.S
1 /*
2  *  Cache-handling routined for MIPS CPUs
3  *
4  *  Copyright (c) 2003  Wolfgang Denk <wd@denx.de>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <asm-offsets.h>
10 #include <config.h>
11 #include <asm/asm.h>
12 #include <asm/regdef.h>
13 #include <asm/mipsregs.h>
14 #include <asm/addrspace.h>
15 #include <asm/cacheops.h>
16
17 #ifndef CONFIG_SYS_MIPS_CACHE_MODE
18 #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
19 #endif
20
21 #define RA              t9
22
23 #define INDEX_BASE      CKSEG0
24
25         .macro  cache_op op addr
26         .set    push
27         .set    noreorder
28         .set    mips3
29         cache   \op, 0(\addr)
30         .set    pop
31         .endm
32
33         .macro  f_fill64 dst, offset, val
34         LONG_S  \val, (\offset +  0 * LONGSIZE)(\dst)
35         LONG_S  \val, (\offset +  1 * LONGSIZE)(\dst)
36         LONG_S  \val, (\offset +  2 * LONGSIZE)(\dst)
37         LONG_S  \val, (\offset +  3 * LONGSIZE)(\dst)
38         LONG_S  \val, (\offset +  4 * LONGSIZE)(\dst)
39         LONG_S  \val, (\offset +  5 * LONGSIZE)(\dst)
40         LONG_S  \val, (\offset +  6 * LONGSIZE)(\dst)
41         LONG_S  \val, (\offset +  7 * LONGSIZE)(\dst)
42 #if LONGSIZE == 4
43         LONG_S  \val, (\offset +  8 * LONGSIZE)(\dst)
44         LONG_S  \val, (\offset +  9 * LONGSIZE)(\dst)
45         LONG_S  \val, (\offset + 10 * LONGSIZE)(\dst)
46         LONG_S  \val, (\offset + 11 * LONGSIZE)(\dst)
47         LONG_S  \val, (\offset + 12 * LONGSIZE)(\dst)
48         LONG_S  \val, (\offset + 13 * LONGSIZE)(\dst)
49         LONG_S  \val, (\offset + 14 * LONGSIZE)(\dst)
50         LONG_S  \val, (\offset + 15 * LONGSIZE)(\dst)
51 #endif
52         .endm
53
54 /*
55  * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
56  */
57 LEAF(mips_init_icache)
58         blez            a1, 9f
59         mtc0            zero, CP0_TAGLO
60         /* clear tag to invalidate */
61         PTR_LI          t0, INDEX_BASE
62         PTR_ADDU        t1, t0, a1
63 1:      cache_op        INDEX_STORE_TAG_I t0
64         PTR_ADDU        t0, a2
65         bne             t0, t1, 1b
66         /* fill once, so data field parity is correct */
67         PTR_LI          t0, INDEX_BASE
68 2:      cache_op        FILL t0
69         PTR_ADDU        t0, a2
70         bne             t0, t1, 2b
71         /* invalidate again - prudent but not strictly neccessary */
72         PTR_LI          t0, INDEX_BASE
73 1:      cache_op        INDEX_STORE_TAG_I t0
74         PTR_ADDU        t0, a2
75         bne             t0, t1, 1b
76 9:      jr              ra
77         END(mips_init_icache)
78
79 /*
80  * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
81  */
82 LEAF(mips_init_dcache)
83         blez            a1, 9f
84         mtc0            zero, CP0_TAGLO
85         /* clear all tags */
86         PTR_LI          t0, INDEX_BASE
87         PTR_ADDU        t1, t0, a1
88 1:      cache_op        INDEX_STORE_TAG_D t0
89         PTR_ADDU        t0, a2
90         bne             t0, t1, 1b
91         /* load from each line (in cached space) */
92         PTR_LI          t0, INDEX_BASE
93 2:      LONG_L          zero, 0(t0)
94         PTR_ADDU        t0, a2
95         bne             t0, t1, 2b
96         /* clear all tags */
97         PTR_LI          t0, INDEX_BASE
98 1:      cache_op        INDEX_STORE_TAG_D t0
99         PTR_ADDU        t0, a2
100         bne             t0, t1, 1b
101 9:      jr              ra
102         END(mips_init_dcache)
103
104 /*
105  * mips_cache_reset - low level initialisation of the primary caches
106  *
107  * This routine initialises the primary caches to ensure that they have good
108  * parity.  It must be called by the ROM before any cached locations are used
109  * to prevent the possibility of data with bad parity being written to memory.
110  *
111  * To initialise the instruction cache it is essential that a source of data
112  * with good parity is available. This routine will initialise an area of
113  * memory starting at location zero to be used as a source of parity.
114  *
115  * RETURNS: N/A
116  *
117  */
118 NESTED(mips_cache_reset, 0, ra)
119         move    RA, ra
120
121 #if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \
122     !defined(CONFIG_SYS_CACHELINE_SIZE)
123         /* read Config1 for use below */
124         mfc0    t5, CP0_CONFIG, 1
125 #endif
126
127 #ifdef CONFIG_SYS_CACHELINE_SIZE
128         li      t7, CONFIG_SYS_CACHELINE_SIZE
129         li      t8, CONFIG_SYS_CACHELINE_SIZE
130 #else
131         /* Detect I-cache line size. */
132         srl     t8, t5, MIPS_CONF1_IL_SHIFT
133         andi    t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT)
134         beqz    t8, 1f
135         li      t6, 2
136         sllv    t8, t6, t8
137
138 1:      /* Detect D-cache line size. */
139         srl     t7, t5, MIPS_CONF1_DL_SHIFT
140         andi    t7, t7, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
141         beqz    t7, 1f
142         li      t6, 2
143         sllv    t7, t6, t7
144 1:
145 #endif
146
147 #ifdef CONFIG_SYS_ICACHE_SIZE
148         li      t2, CONFIG_SYS_ICACHE_SIZE
149 #else
150         /* Detect I-cache size. */
151         srl     t6, t5, MIPS_CONF1_IS_SHIFT
152         andi    t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT)
153         li      t4, 32
154         xori    t2, t6, 0x7
155         beqz    t2, 1f
156         addi    t6, t6, 1
157         sllv    t4, t4, t6
158 1:      /* At this point t4 == I-cache sets. */
159         mul     t2, t4, t8
160         srl     t6, t5, MIPS_CONF1_IA_SHIFT
161         andi    t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT)
162         addi    t6, t6, 1
163         /* At this point t6 == I-cache ways. */
164         mul     t2, t2, t6
165 #endif
166
167 #ifdef CONFIG_SYS_DCACHE_SIZE
168         li      t3, CONFIG_SYS_DCACHE_SIZE
169 #else
170         /* Detect D-cache size. */
171         srl     t6, t5, MIPS_CONF1_DS_SHIFT
172         andi    t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
173         li      t4, 32
174         xori    t3, t6, 0x7
175         beqz    t3, 1f
176         addi    t6, t6, 1
177         sllv    t4, t4, t6
178 1:      /* At this point t4 == I-cache sets. */
179         mul     t3, t4, t7
180         srl     t6, t5, MIPS_CONF1_DA_SHIFT
181         andi    t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
182         addi    t6, t6, 1
183         /* At this point t6 == I-cache ways. */
184         mul     t3, t3, t6
185 #endif
186
187         /* Determine the largest L1 cache size */
188 #if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
189 #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
190         li      v0, CONFIG_SYS_ICACHE_SIZE
191 #else
192         li      v0, CONFIG_SYS_DCACHE_SIZE
193 #endif
194 #else
195         move    v0, t2
196         sltu    t1, t2, t3
197         movn    v0, t3, t1
198 #endif
199         /*
200          * Now clear that much memory starting from zero.
201          */
202         PTR_LI          a0, CKSEG1
203         PTR_ADDU        a1, a0, v0
204 2:      PTR_ADDIU       a0, 64
205         f_fill64        a0, -64, zero
206         bne             a0, a1, 2b
207
208         /*
209          * The caches are probably in an indeterminate state,
210          * so we force good parity into them by doing an
211          * invalidate, load/fill, invalidate for each line.
212          */
213
214         /*
215          * Assume bottom of RAM will generate good parity for the cache.
216          */
217
218         /*
219          * Initialize the I-cache first,
220          */
221         move    a1, t2
222         move    a2, t8
223         PTR_LA  v1, mips_init_icache
224         jalr    v1
225
226         /*
227          * then initialize D-cache.
228          */
229         move    a1, t3
230         move    a2, t7
231         PTR_LA  v1, mips_init_dcache
232         jalr    v1
233
234         jr      RA
235         END(mips_cache_reset)
236
237 /*
238  * dcache_status - get cache status
239  *
240  * RETURNS: 0 - cache disabled; 1 - cache enabled
241  *
242  */
243 LEAF(dcache_status)
244         mfc0    t0, CP0_CONFIG
245         li      t1, CONF_CM_UNCACHED
246         andi    t0, t0, CONF_CM_CMASK
247         move    v0, zero
248         beq     t0, t1, 2f
249         li      v0, 1
250 2:      jr      ra
251         END(dcache_status)
252
253 /*
254  * dcache_disable - disable cache
255  *
256  * RETURNS: N/A
257  *
258  */
259 LEAF(dcache_disable)
260         mfc0    t0, CP0_CONFIG
261         li      t1, -8
262         and     t0, t0, t1
263         ori     t0, t0, CONF_CM_UNCACHED
264         mtc0    t0, CP0_CONFIG
265         jr      ra
266         END(dcache_disable)
267
268 /*
269  * dcache_enable - enable cache
270  *
271  * RETURNS: N/A
272  *
273  */
274 LEAF(dcache_enable)
275         mfc0    t0, CP0_CONFIG
276         ori     t0, CONF_CM_CMASK
277         xori    t0, CONF_CM_CMASK
278         ori     t0, CONFIG_SYS_MIPS_CACHE_MODE
279         mtc0    t0, CP0_CONFIG
280         jr      ra
281         END(dcache_enable)