xref: /rk3399_rockchip-uboot/arch/mips/lib/cache_init.S (revision b2b135d980a7171c9b0eefbb38861ccbe9a47f97)
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 INDEX_BASE	CKSEG0
22
23	.macro	f_fill64 dst, offset, val
24	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
25	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
26	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
27	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
28	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
29	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
30	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
31	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
32#if LONGSIZE == 4
33	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
34	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
35	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
36	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
37	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
38	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
39	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
40	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
41#endif
42	.endm
43
44	.macro cache_loop	curr, end, line_sz, op
4510:	cache		\op, 0(\curr)
46	PTR_ADDU	\curr, \curr, \line_sz
47	bne		\curr, \end, 10b
48	.endm
49
50	.macro	l1_info		sz, line_sz, off
51	.set	push
52	.set	noat
53
54	mfc0	$1, CP0_CONFIG, 1
55
56	/* detect line size */
57	srl	\line_sz, $1, \off + MIPS_CONF1_DL_SHF - MIPS_CONF1_DA_SHF
58	andi	\line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHF)
59	move	\sz, zero
60	beqz	\line_sz, 10f
61	li	\sz, 2
62	sllv	\line_sz, \sz, \line_sz
63
64	/* detect associativity */
65	srl	\sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF
66	andi	\sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF)
67	addiu	\sz, \sz, 1
68
69	/* sz *= line_sz */
70	mul	\sz, \sz, \line_sz
71
72	/* detect log32(sets) */
73	srl	$1, $1, \off + MIPS_CONF1_DS_SHF - MIPS_CONF1_DA_SHF
74	andi	$1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHF)
75	addiu	$1, $1, 1
76	andi	$1, $1, 0x7
77
78	/* sz <<= log32(sets) */
79	sllv	\sz, \sz, $1
80
81	/* sz *= 32 */
82	li	$1, 32
83	mul	\sz, \sz, $1
8410:
85	.set	pop
86	.endm
87/*
88 * mips_cache_reset - low level initialisation of the primary caches
89 *
90 * This routine initialises the primary caches to ensure that they have good
91 * parity.  It must be called by the ROM before any cached locations are used
92 * to prevent the possibility of data with bad parity being written to memory.
93 *
94 * To initialise the instruction cache it is essential that a source of data
95 * with good parity is available. This routine will initialise an area of
96 * memory starting at location zero to be used as a source of parity.
97 *
98 * RETURNS: N/A
99 *
100 */
101#define R_IC_SIZE	t2
102#define R_IC_LINE	t8
103#define R_DC_SIZE	t3
104#define R_DC_LINE	t9
105LEAF(mips_cache_reset)
106#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
107	li	R_IC_SIZE, CONFIG_SYS_ICACHE_SIZE
108	li	R_IC_LINE, CONFIG_SYS_ICACHE_LINE_SIZE
109#else
110	l1_info	R_IC_SIZE, R_IC_LINE, MIPS_CONF1_IA_SHF
111#endif
112
113#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
114	li	R_DC_SIZE, CONFIG_SYS_DCACHE_SIZE
115	li	R_DC_LINE, CONFIG_SYS_DCACHE_LINE_SIZE
116#else
117	l1_info	R_DC_SIZE, R_DC_LINE, MIPS_CONF1_DA_SHF
118#endif
119
120#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
121
122	/* Determine the largest L1 cache size */
123#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
124#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
125	li	v0, CONFIG_SYS_ICACHE_SIZE
126#else
127	li	v0, CONFIG_SYS_DCACHE_SIZE
128#endif
129#else
130	move	v0, R_IC_SIZE
131	sltu	t1, R_IC_SIZE, R_DC_SIZE
132	movn	v0, R_DC_SIZE, t1
133#endif
134	/*
135	 * Now clear that much memory starting from zero.
136	 */
137	PTR_LI		a0, CKSEG1
138	PTR_ADDU	a1, a0, v0
1392:	PTR_ADDIU	a0, 64
140	f_fill64	a0, -64, zero
141	bne		a0, a1, 2b
142
143#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
144
145	/*
146	 * The TagLo registers used depend upon the CPU implementation, but the
147	 * architecture requires that it is safe for software to write to both
148	 * TagLo selects 0 & 2 covering supported cases.
149	 */
150	mtc0		zero, CP0_TAGLO
151	mtc0		zero, CP0_TAGLO, 2
152
153	/*
154	 * The caches are probably in an indeterminate state, so we force good
155	 * parity into them by doing an invalidate for each line. If
156	 * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to
157	 * perform a load/fill & a further invalidate for each line, assuming
158	 * that the bottom of RAM (having just been cleared) will generate good
159	 * parity for the cache.
160	 */
161
162	/*
163	 * Initialize the I-cache first,
164	 */
165	blez		R_IC_SIZE, 1f
166	PTR_LI		t0, INDEX_BASE
167	PTR_ADDU	t1, t0, R_IC_SIZE
168	/* clear tag to invalidate */
169	cache_loop	t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
170#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
171	/* fill once, so data field parity is correct */
172	PTR_LI		t0, INDEX_BASE
173	cache_loop	t0, t1, R_IC_LINE, FILL
174	/* invalidate again - prudent but not strictly neccessary */
175	PTR_LI		t0, INDEX_BASE
176	cache_loop	t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
177#endif
178
179	/* Enable use of the I-cache by setting Config.K0 */
180	sync
181	mfc0		t0, CP0_CONFIG
182	li		t1, CONFIG_SYS_MIPS_CACHE_MODE
183#if __mips_isa_rev >= 2
184	ins		t0, t1, 0, 3
185#else
186	ori		t0, t0, CONF_CM_CMASK
187	xori		t0, t0, CONF_CM_CMASK
188	or		t0, t0, t1
189#endif
190	mtc0		t0, CP0_CONFIG
191
192	/*
193	 * then initialize D-cache.
194	 */
1951:	blez		R_DC_SIZE, 3f
196	PTR_LI		t0, INDEX_BASE
197	PTR_ADDU	t1, t0, R_DC_SIZE
198	/* clear all tags */
199	cache_loop	t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
200#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
201	/* load from each line (in cached space) */
202	PTR_LI		t0, INDEX_BASE
2032:	LONG_L		zero, 0(t0)
204	PTR_ADDU	t0, R_DC_LINE
205	bne		t0, t1, 2b
206	/* clear all tags */
207	PTR_LI		t0, INDEX_BASE
208	cache_loop	t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
209#endif
210
2113:	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 */
220LEAF(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
2272:	jr	ra
228	END(dcache_status)
229
230/*
231 * dcache_disable - disable cache
232 *
233 * RETURNS: N/A
234 *
235 */
236LEAF(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 */
251LEAF(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)
259