xref: /rk3399_rockchip-uboot/arch/mips/lib/cache_init.S (revision 536cb7ce1aca10c326ac864b3e1d05ab57b3ec7e)
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 */
53LEAF(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
591:	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
642:	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
691:	cache		INDEX_STORE_TAG_I, 0(t0)
70	PTR_ADDU	t0, a2
71	bne		t0, t1, 1b
729:	jr		ra
73	END(mips_init_icache)
74
75/*
76 * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
77 */
78LEAF(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
841:	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
892:	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
941:	cache		INDEX_STORE_TAG_D, 0(t0)
95	PTR_ADDU	t0, a2
96	bne		t0, t1, 1b
979:	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
13410:
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 */
151NESTED(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
1852:	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 */
224LEAF(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
2312:	jr	ra
232	END(dcache_status)
233
234/*
235 * dcache_disable - disable cache
236 *
237 * RETURNS: N/A
238 *
239 */
240LEAF(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 */
255LEAF(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)
263