2e036d9b979445e68c2c145bcc725236991d5494
[oweals/u-boot.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         .macro  l1_info         sz, line_sz, off
101         .set    push
102         .set    noat
103
104         mfc0    $1, CP0_CONFIG, 1
105
106         /* detect line size */
107         srl     \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT
108         andi    \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
109         move    \sz, zero
110         beqz    \line_sz, 10f
111         li      \sz, 2
112         sllv    \line_sz, \sz, \line_sz
113
114         /* detect associativity */
115         srl     \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT
116         andi    \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
117         addi    \sz, \sz, 1
118
119         /* sz *= line_sz */
120         mul     \sz, \sz, \line_sz
121
122         /* detect log32(sets) */
123         srl     $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT
124         andi    $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
125         addiu   $1, $1, 1
126         andi    $1, $1, 0x7
127
128         /* sz <<= log32(sets) */
129         sllv    \sz, \sz, $1
130
131         /* sz *= 32 */
132         li      $1, 32
133         mul     \sz, \sz, $1
134 10:
135         .set    pop
136         .endm
137 /*
138  * mips_cache_reset - low level initialisation of the primary caches
139  *
140  * This routine initialises the primary caches to ensure that they have good
141  * parity.  It must be called by the ROM before any cached locations are used
142  * to prevent the possibility of data with bad parity being written to memory.
143  *
144  * To initialise the instruction cache it is essential that a source of data
145  * with good parity is available. This routine will initialise an area of
146  * memory starting at location zero to be used as a source of parity.
147  *
148  * RETURNS: N/A
149  *
150  */
151 NESTED(mips_cache_reset, 0, ra)
152         move    RA, ra
153
154 #ifdef CONFIG_SYS_ICACHE_SIZE
155         li      t2, CONFIG_SYS_ICACHE_SIZE
156         li      t8, CONFIG_SYS_CACHELINE_SIZE
157 #else
158         l1_info t2, t8, MIPS_CONF1_IA_SHIFT
159 #endif
160
161 #ifdef CONFIG_SYS_DCACHE_SIZE
162         li      t3, CONFIG_SYS_DCACHE_SIZE
163         li      t9, CONFIG_SYS_CACHELINE_SIZE
164 #else
165         l1_info t3, t9, MIPS_CONF1_DA_SHIFT
166 #endif
167
168         /* Determine the largest L1 cache size */
169 #if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
170 #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
171         li      v0, CONFIG_SYS_ICACHE_SIZE
172 #else
173         li      v0, CONFIG_SYS_DCACHE_SIZE
174 #endif
175 #else
176         move    v0, t2
177         sltu    t1, t2, t3
178         movn    v0, t3, t1
179 #endif
180         /*
181          * Now clear that much memory starting from zero.
182          */
183         PTR_LI          a0, CKSEG1
184         PTR_ADDU        a1, a0, v0
185 2:      PTR_ADDIU       a0, 64
186         f_fill64        a0, -64, zero
187         bne             a0, a1, 2b
188
189         /*
190          * The caches are probably in an indeterminate state,
191          * so we force good parity into them by doing an
192          * invalidate, load/fill, invalidate for each line.
193          */
194
195         /*
196          * Assume bottom of RAM will generate good parity for the cache.
197          */
198
199         /*
200          * Initialize the I-cache first,
201          */
202         move    a1, t2
203         move    a2, t8
204         PTR_LA  v1, mips_init_icache
205         jalr    v1
206
207         /*
208          * then initialize D-cache.
209          */
210         move    a1, t3
211         move    a2, t9
212         PTR_LA  v1, mips_init_dcache
213         jalr    v1
214
215         jr      RA
216         END(mips_cache_reset)
217
218 /*
219  * dcache_status - get cache status
220  *
221  * RETURNS: 0 - cache disabled; 1 - cache enabled
222  *
223  */
224 LEAF(dcache_status)
225         mfc0    t0, CP0_CONFIG
226         li      t1, CONF_CM_UNCACHED
227         andi    t0, t0, CONF_CM_CMASK
228         move    v0, zero
229         beq     t0, t1, 2f
230         li      v0, 1
231 2:      jr      ra
232         END(dcache_status)
233
234 /*
235  * dcache_disable - disable cache
236  *
237  * RETURNS: N/A
238  *
239  */
240 LEAF(dcache_disable)
241         mfc0    t0, CP0_CONFIG
242         li      t1, -8
243         and     t0, t0, t1
244         ori     t0, t0, CONF_CM_UNCACHED
245         mtc0    t0, CP0_CONFIG
246         jr      ra
247         END(dcache_disable)
248
249 /*
250  * dcache_enable - enable cache
251  *
252  * RETURNS: N/A
253  *
254  */
255 LEAF(dcache_enable)
256         mfc0    t0, CP0_CONFIG
257         ori     t0, CONF_CM_CMASK
258         xori    t0, CONF_CM_CMASK
259         ori     t0, CONFIG_SYS_MIPS_CACHE_MODE
260         mtc0    t0, CP0_CONFIG
261         jr      ra
262         END(dcache_enable)