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