xref: /openbmc/u-boot/arch/mips/lib/cache_init.S (revision 33b5c9b2092e10fa3b8b325823c846368f25bba9)
14a5d8898SPaul Burton/*
24a5d8898SPaul Burton *  Cache-handling routined for MIPS CPUs
34a5d8898SPaul Burton *
44a5d8898SPaul Burton *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
54a5d8898SPaul Burton *
64a5d8898SPaul Burton * SPDX-License-Identifier:	GPL-2.0+
74a5d8898SPaul Burton */
84a5d8898SPaul Burton
94a5d8898SPaul Burton#include <asm-offsets.h>
104a5d8898SPaul Burton#include <config.h>
114a5d8898SPaul Burton#include <asm/asm.h>
124a5d8898SPaul Burton#include <asm/regdef.h>
134a5d8898SPaul Burton#include <asm/mipsregs.h>
144a5d8898SPaul Burton#include <asm/addrspace.h>
154a5d8898SPaul Burton#include <asm/cacheops.h>
164a5d8898SPaul Burton
174a5d8898SPaul Burton#ifndef CONFIG_SYS_MIPS_CACHE_MODE
184a5d8898SPaul Burton#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
194a5d8898SPaul Burton#endif
204a5d8898SPaul Burton
214a5d8898SPaul Burton#define INDEX_BASE	CKSEG0
224a5d8898SPaul Burton
234a5d8898SPaul Burton	.macro	f_fill64 dst, offset, val
244a5d8898SPaul Burton	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
254a5d8898SPaul Burton	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
264a5d8898SPaul Burton	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
274a5d8898SPaul Burton	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
284a5d8898SPaul Burton	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
294a5d8898SPaul Burton	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
304a5d8898SPaul Burton	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
314a5d8898SPaul Burton	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
324a5d8898SPaul Burton#if LONGSIZE == 4
334a5d8898SPaul Burton	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
344a5d8898SPaul Burton	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
354a5d8898SPaul Burton	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
364a5d8898SPaul Burton	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
374a5d8898SPaul Burton	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
384a5d8898SPaul Burton	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
394a5d8898SPaul Burton	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
404a5d8898SPaul Burton	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
414a5d8898SPaul Burton#endif
424a5d8898SPaul Burton	.endm
434a5d8898SPaul Burton
44ac22fecaSPaul Burton	.macro cache_loop	curr, end, line_sz, op
45ac22fecaSPaul Burton10:	cache		\op, 0(\curr)
46ac22fecaSPaul Burton	PTR_ADDU	\curr, \curr, \line_sz
47ac22fecaSPaul Burton	bne		\curr, \end, 10b
48ac22fecaSPaul Burton	.endm
49ac22fecaSPaul Burton
50536cb7ceSPaul Burton	.macro	l1_info		sz, line_sz, off
51536cb7ceSPaul Burton	.set	push
52536cb7ceSPaul Burton	.set	noat
53536cb7ceSPaul Burton
54536cb7ceSPaul Burton	mfc0	$1, CP0_CONFIG, 1
55536cb7ceSPaul Burton
56536cb7ceSPaul Burton	/* detect line size */
57a3ab2ae7SDaniel Schwierzeck	srl	\line_sz, $1, \off + MIPS_CONF1_DL_SHF - MIPS_CONF1_DA_SHF
58a3ab2ae7SDaniel Schwierzeck	andi	\line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHF)
59536cb7ceSPaul Burton	move	\sz, zero
60536cb7ceSPaul Burton	beqz	\line_sz, 10f
61536cb7ceSPaul Burton	li	\sz, 2
62536cb7ceSPaul Burton	sllv	\line_sz, \sz, \line_sz
63536cb7ceSPaul Burton
64536cb7ceSPaul Burton	/* detect associativity */
65a3ab2ae7SDaniel Schwierzeck	srl	\sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF
66a3ab2ae7SDaniel Schwierzeck	andi	\sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF)
679f8ac824SPaul Burton	addiu	\sz, \sz, 1
68536cb7ceSPaul Burton
69536cb7ceSPaul Burton	/* sz *= line_sz */
70536cb7ceSPaul Burton	mul	\sz, \sz, \line_sz
71536cb7ceSPaul Burton
72536cb7ceSPaul Burton	/* detect log32(sets) */
73a3ab2ae7SDaniel Schwierzeck	srl	$1, $1, \off + MIPS_CONF1_DS_SHF - MIPS_CONF1_DA_SHF
74a3ab2ae7SDaniel Schwierzeck	andi	$1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHF)
75536cb7ceSPaul Burton	addiu	$1, $1, 1
76536cb7ceSPaul Burton	andi	$1, $1, 0x7
77536cb7ceSPaul Burton
78536cb7ceSPaul Burton	/* sz <<= log32(sets) */
79536cb7ceSPaul Burton	sllv	\sz, \sz, $1
80536cb7ceSPaul Burton
81536cb7ceSPaul Burton	/* sz *= 32 */
82536cb7ceSPaul Burton	li	$1, 32
83536cb7ceSPaul Burton	mul	\sz, \sz, $1
84536cb7ceSPaul Burton10:
85536cb7ceSPaul Burton	.set	pop
86536cb7ceSPaul Burton	.endm
874a5d8898SPaul Burton/*
884a5d8898SPaul Burton * mips_cache_reset - low level initialisation of the primary caches
894a5d8898SPaul Burton *
904a5d8898SPaul Burton * This routine initialises the primary caches to ensure that they have good
914a5d8898SPaul Burton * parity.  It must be called by the ROM before any cached locations are used
924a5d8898SPaul Burton * to prevent the possibility of data with bad parity being written to memory.
934a5d8898SPaul Burton *
944a5d8898SPaul Burton * To initialise the instruction cache it is essential that a source of data
954a5d8898SPaul Burton * with good parity is available. This routine will initialise an area of
964a5d8898SPaul Burton * memory starting at location zero to be used as a source of parity.
974a5d8898SPaul Burton *
984a5d8898SPaul Burton * RETURNS: N/A
994a5d8898SPaul Burton *
1004a5d8898SPaul Burton */
101ca4e833cSPaul BurtonLEAF(mips_cache_reset)
102ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
1034a5d8898SPaul Burton	li	t2, CONFIG_SYS_ICACHE_SIZE
10437228621SPaul Burton	li	t8, CONFIG_SYS_ICACHE_LINE_SIZE
1054a5d8898SPaul Burton#else
106a3ab2ae7SDaniel Schwierzeck	l1_info	t2, t8, MIPS_CONF1_IA_SHF
1074a5d8898SPaul Burton#endif
1084a5d8898SPaul Burton
109ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
1104a5d8898SPaul Burton	li	t3, CONFIG_SYS_DCACHE_SIZE
11137228621SPaul Burton	li	t9, CONFIG_SYS_DCACHE_LINE_SIZE
1124a5d8898SPaul Burton#else
113a3ab2ae7SDaniel Schwierzeck	l1_info	t3, t9, MIPS_CONF1_DA_SHF
1144a5d8898SPaul Burton#endif
1154a5d8898SPaul Burton
116dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
117dd7c7200SPaul Burton
1184a5d8898SPaul Burton	/* Determine the largest L1 cache size */
119ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
1204a5d8898SPaul Burton#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
1214a5d8898SPaul Burton	li	v0, CONFIG_SYS_ICACHE_SIZE
1224a5d8898SPaul Burton#else
1234a5d8898SPaul Burton	li	v0, CONFIG_SYS_DCACHE_SIZE
1244a5d8898SPaul Burton#endif
1254a5d8898SPaul Burton#else
1264a5d8898SPaul Burton	move	v0, t2
1274a5d8898SPaul Burton	sltu	t1, t2, t3
1284a5d8898SPaul Burton	movn	v0, t3, t1
1294a5d8898SPaul Burton#endif
1304a5d8898SPaul Burton	/*
1314a5d8898SPaul Burton	 * Now clear that much memory starting from zero.
1324a5d8898SPaul Burton	 */
1334a5d8898SPaul Burton	PTR_LI		a0, CKSEG1
1344a5d8898SPaul Burton	PTR_ADDU	a1, a0, v0
1354a5d8898SPaul Burton2:	PTR_ADDIU	a0, 64
1364a5d8898SPaul Burton	f_fill64	a0, -64, zero
1374a5d8898SPaul Burton	bne		a0, a1, 2b
1384a5d8898SPaul Burton
139dd7c7200SPaul Burton#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
1404a5d8898SPaul Burton
1414a5d8898SPaul Burton	/*
1428755d507SPaul Burton	 * The TagLo registers used depend upon the CPU implementation, but the
1438755d507SPaul Burton	 * architecture requires that it is safe for software to write to both
1448755d507SPaul Burton	 * TagLo selects 0 & 2 covering supported cases.
1458755d507SPaul Burton	 */
1468755d507SPaul Burton	mtc0		zero, CP0_TAGLO
1478755d507SPaul Burton	mtc0		zero, CP0_TAGLO, 2
1488755d507SPaul Burton
1498755d507SPaul Burton	/*
150dd7c7200SPaul Burton	 * The caches are probably in an indeterminate state, so we force good
151dd7c7200SPaul Burton	 * parity into them by doing an invalidate for each line. If
152dd7c7200SPaul Burton	 * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to
153dd7c7200SPaul Burton	 * perform a load/fill & a further invalidate for each line, assuming
154dd7c7200SPaul Burton	 * that the bottom of RAM (having just been cleared) will generate good
155dd7c7200SPaul Burton	 * parity for the cache.
1564a5d8898SPaul Burton	 */
1574a5d8898SPaul Burton
1584a5d8898SPaul Burton	/*
1594a5d8898SPaul Burton	 * Initialize the I-cache first,
1604a5d8898SPaul Burton	 */
161ca4e833cSPaul Burton	blez		t2, 1f
162ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
163ca4e833cSPaul Burton	PTR_ADDU	t1, t0, t2
164ca4e833cSPaul Burton	/* clear tag to invalidate */
165ca4e833cSPaul Burton	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
166dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
167ca4e833cSPaul Burton	/* fill once, so data field parity is correct */
168ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
169ca4e833cSPaul Burton	cache_loop	t0, t1, t8, FILL
170ca4e833cSPaul Burton	/* invalidate again - prudent but not strictly neccessary */
171ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
172ca4e833cSPaul Burton	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
173dd7c7200SPaul Burton#endif
1744a5d8898SPaul Burton
175*33b5c9b2SPaul Burton	/* Enable use of the I-cache by setting Config.K0 */
176*33b5c9b2SPaul Burton	sync
177*33b5c9b2SPaul Burton	mfc0		t0, CP0_CONFIG
178*33b5c9b2SPaul Burton	li		t1, CONFIG_SYS_MIPS_CACHE_MODE
179*33b5c9b2SPaul Burton#if __mips_isa_rev >= 2
180*33b5c9b2SPaul Burton	ins		t0, t1, 0, 3
181*33b5c9b2SPaul Burton#else
182*33b5c9b2SPaul Burton	ori		t0, t0, CONF_CM_CMASK
183*33b5c9b2SPaul Burton	xori		t0, t0, CONF_CM_CMASK
184*33b5c9b2SPaul Burton	or		t0, t0, t1
185*33b5c9b2SPaul Burton#endif
186*33b5c9b2SPaul Burton	mtc0		t0, CP0_CONFIG
187*33b5c9b2SPaul Burton
1884a5d8898SPaul Burton	/*
1894a5d8898SPaul Burton	 * then initialize D-cache.
1904a5d8898SPaul Burton	 */
191ca4e833cSPaul Burton1:	blez		t3, 3f
192ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
193ca4e833cSPaul Burton	PTR_ADDU	t1, t0, t3
194ca4e833cSPaul Burton	/* clear all tags */
195ca4e833cSPaul Burton	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
196dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
197ca4e833cSPaul Burton	/* load from each line (in cached space) */
198ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
199ca4e833cSPaul Burton2:	LONG_L		zero, 0(t0)
200ca4e833cSPaul Burton	PTR_ADDU	t0, t9
201ca4e833cSPaul Burton	bne		t0, t1, 2b
202ca4e833cSPaul Burton	/* clear all tags */
203ca4e833cSPaul Burton	PTR_LI		t0, INDEX_BASE
204ca4e833cSPaul Burton	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
205dd7c7200SPaul Burton#endif
2064a5d8898SPaul Burton
207ca4e833cSPaul Burton3:	jr	ra
2084a5d8898SPaul Burton	END(mips_cache_reset)
2094a5d8898SPaul Burton
2104a5d8898SPaul Burton/*
2114a5d8898SPaul Burton * dcache_status - get cache status
2124a5d8898SPaul Burton *
2134a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled
2144a5d8898SPaul Burton *
2154a5d8898SPaul Burton */
2164a5d8898SPaul BurtonLEAF(dcache_status)
2174a5d8898SPaul Burton	mfc0	t0, CP0_CONFIG
2184a5d8898SPaul Burton	li	t1, CONF_CM_UNCACHED
2194a5d8898SPaul Burton	andi	t0, t0, CONF_CM_CMASK
2204a5d8898SPaul Burton	move	v0, zero
2214a5d8898SPaul Burton	beq	t0, t1, 2f
2224a5d8898SPaul Burton	li	v0, 1
2234a5d8898SPaul Burton2:	jr	ra
2244a5d8898SPaul Burton	END(dcache_status)
2254a5d8898SPaul Burton
2264a5d8898SPaul Burton/*
2274a5d8898SPaul Burton * dcache_disable - disable cache
2284a5d8898SPaul Burton *
2294a5d8898SPaul Burton * RETURNS: N/A
2304a5d8898SPaul Burton *
2314a5d8898SPaul Burton */
2324a5d8898SPaul BurtonLEAF(dcache_disable)
2334a5d8898SPaul Burton	mfc0	t0, CP0_CONFIG
2344a5d8898SPaul Burton	li	t1, -8
2354a5d8898SPaul Burton	and	t0, t0, t1
2364a5d8898SPaul Burton	ori	t0, t0, CONF_CM_UNCACHED
2374a5d8898SPaul Burton	mtc0	t0, CP0_CONFIG
2384a5d8898SPaul Burton	jr	ra
2394a5d8898SPaul Burton	END(dcache_disable)
2404a5d8898SPaul Burton
2414a5d8898SPaul Burton/*
2424a5d8898SPaul Burton * dcache_enable - enable cache
2434a5d8898SPaul Burton *
2444a5d8898SPaul Burton * RETURNS: N/A
2454a5d8898SPaul Burton *
2464a5d8898SPaul Burton */
2474a5d8898SPaul BurtonLEAF(dcache_enable)
2484a5d8898SPaul Burton	mfc0	t0, CP0_CONFIG
2494a5d8898SPaul Burton	ori	t0, CONF_CM_CMASK
2504a5d8898SPaul Burton	xori	t0, CONF_CM_CMASK
2514a5d8898SPaul Burton	ori	t0, CONFIG_SYS_MIPS_CACHE_MODE
2524a5d8898SPaul Burton	mtc0	t0, CP0_CONFIG
2534a5d8898SPaul Burton	jr	ra
2544a5d8898SPaul Burton	END(dcache_enable)
255