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