xref: /rk3399_rockchip-uboot/arch/mips/lib/cache_init.S (revision ac22feca1135b81ecc4d38995e98b59943d1bbf5)
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
5110:	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 */
59LEAF(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
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	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
872:	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
939:	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
13010:
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 */
147NESTED(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
1812:	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 */
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