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