]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/lib/cache_init.S
MIPS: refactor cache loops to a macro
[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         .macro cache_loop       curr, end, line_sz, op
51 10:     cache           \op, 0(\curr)
52         PTR_ADDU        \curr, \curr, \line_sz
53         bne             \curr, \end, 10b
54         .endm
55
56 /*
57  * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
58  */
59 LEAF(mips_init_icache)
60         blez            a1, 9f
61         mtc0            zero, CP0_TAGLO
62         PTR_LI          t0, INDEX_BASE
63         PTR_ADDU        t1, t0, a1
64         /* clear tag to invalidate */
65         cache_loop      t0, t1, a2, INDEX_STORE_TAG_I
66         /* fill once, so data field parity is correct */
67         PTR_LI          t0, INDEX_BASE
68         cache_loop      t0, t1, a2, FILL
69         /* invalidate again - prudent but not strictly neccessary */
70         PTR_LI          t0, INDEX_BASE
71         cache_loop      t0, t1, a2, INDEX_STORE_TAG_I
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         PTR_LI          t0, INDEX_BASE
82         PTR_ADDU        t1, t0, a1
83         /* clear all tags */
84         cache_loop      t0, t1, a2, INDEX_STORE_TAG_D
85         /* load from each line (in cached space) */
86         PTR_LI          t0, INDEX_BASE
87 2:      LONG_L          zero, 0(t0)
88         PTR_ADDU        t0, a2
89         bne             t0, t1, 2b
90         /* clear all tags */
91         PTR_LI          t0, INDEX_BASE
92         cache_loop      t0, t1, a2, INDEX_STORE_TAG_D
93 9:      jr              ra
94         END(mips_init_dcache)
95
96         .macro  l1_info         sz, line_sz, off
97         .set    push
98         .set    noat
99
100         mfc0    $1, CP0_CONFIG, 1
101
102         /* detect line size */
103         srl     \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT
104         andi    \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
105         move    \sz, zero
106         beqz    \line_sz, 10f
107         li      \sz, 2
108         sllv    \line_sz, \sz, \line_sz
109
110         /* detect associativity */
111         srl     \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT
112         andi    \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
113         addi    \sz, \sz, 1
114
115         /* sz *= line_sz */
116         mul     \sz, \sz, \line_sz
117
118         /* detect log32(sets) */
119         srl     $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT
120         andi    $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
121         addiu   $1, $1, 1
122         andi    $1, $1, 0x7
123
124         /* sz <<= log32(sets) */
125         sllv    \sz, \sz, $1
126
127         /* sz *= 32 */
128         li      $1, 32
129         mul     \sz, \sz, $1
130 10:
131         .set    pop
132         .endm
133 /*
134  * mips_cache_reset - low level initialisation of the primary caches
135  *
136  * This routine initialises the primary caches to ensure that they have good
137  * parity.  It must be called by the ROM before any cached locations are used
138  * to prevent the possibility of data with bad parity being written to memory.
139  *
140  * To initialise the instruction cache it is essential that a source of data
141  * with good parity is available. This routine will initialise an area of
142  * memory starting at location zero to be used as a source of parity.
143  *
144  * RETURNS: N/A
145  *
146  */
147 NESTED(mips_cache_reset, 0, ra)
148         move    RA, ra
149
150 #ifdef CONFIG_SYS_ICACHE_SIZE
151         li      t2, CONFIG_SYS_ICACHE_SIZE
152         li      t8, CONFIG_SYS_CACHELINE_SIZE
153 #else
154         l1_info t2, t8, MIPS_CONF1_IA_SHIFT
155 #endif
156
157 #ifdef CONFIG_SYS_DCACHE_SIZE
158         li      t3, CONFIG_SYS_DCACHE_SIZE
159         li      t9, CONFIG_SYS_CACHELINE_SIZE
160 #else
161         l1_info t3, t9, MIPS_CONF1_DA_SHIFT
162 #endif
163
164         /* Determine the largest L1 cache size */
165 #if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
166 #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
167         li      v0, CONFIG_SYS_ICACHE_SIZE
168 #else
169         li      v0, CONFIG_SYS_DCACHE_SIZE
170 #endif
171 #else
172         move    v0, t2
173         sltu    t1, t2, t3
174         movn    v0, t3, t1
175 #endif
176         /*
177          * Now clear that much memory starting from zero.
178          */
179         PTR_LI          a0, CKSEG1
180         PTR_ADDU        a1, a0, v0
181 2:      PTR_ADDIU       a0, 64
182         f_fill64        a0, -64, zero
183         bne             a0, a1, 2b
184
185         /*
186          * The caches are probably in an indeterminate state,
187          * so we force good parity into them by doing an
188          * invalidate, load/fill, invalidate for each line.
189          */
190
191         /*
192          * Assume bottom of RAM will generate good parity for the cache.
193          */
194
195         /*
196          * Initialize the I-cache first,
197          */
198         move    a1, t2
199         move    a2, t8
200         PTR_LA  v1, mips_init_icache
201         jalr    v1
202
203         /*
204          * then initialize D-cache.
205          */
206         move    a1, t3
207         move    a2, t9
208         PTR_LA  v1, mips_init_dcache
209         jalr    v1
210
211         jr      RA
212         END(mips_cache_reset)
213
214 /*
215  * dcache_status - get cache status
216  *
217  * RETURNS: 0 - cache disabled; 1 - cache enabled
218  *
219  */
220 LEAF(dcache_status)
221         mfc0    t0, CP0_CONFIG
222         li      t1, CONF_CM_UNCACHED
223         andi    t0, t0, CONF_CM_CMASK
224         move    v0, zero
225         beq     t0, t1, 2f
226         li      v0, 1
227 2:      jr      ra
228         END(dcache_status)
229
230 /*
231  * dcache_disable - disable cache
232  *
233  * RETURNS: N/A
234  *
235  */
236 LEAF(dcache_disable)
237         mfc0    t0, CP0_CONFIG
238         li      t1, -8
239         and     t0, t0, t1
240         ori     t0, t0, CONF_CM_UNCACHED
241         mtc0    t0, CP0_CONFIG
242         jr      ra
243         END(dcache_disable)
244
245 /*
246  * dcache_enable - enable cache
247  *
248  * RETURNS: N/A
249  *
250  */
251 LEAF(dcache_enable)
252         mfc0    t0, CP0_CONFIG
253         ori     t0, CONF_CM_CMASK
254         xori    t0, CONF_CM_CMASK
255         ori     t0, CONFIG_SYS_MIPS_CACHE_MODE
256         mtc0    t0, CP0_CONFIG
257         jr      ra
258         END(dcache_enable)