1/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su)	*/
2/* cache manipulation adapted from Broadcom code 	*/
3/* idea taken from original bunzip2 decompressor code	*/
4/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org)	*/
5/* Licensed under the linux kernel's version of the GPL.*/
6
7#include <asm/asm.h>
8#include <asm/regdef.h>
9
10#define KSEG0		0x80000000
11
12#define C0_CONFIG	$16
13#define C0_TAGLO	$28
14#define C0_TAGHI	$29
15
16#define	CONF1_DA_SHIFT	7			/* D$ associativity */
17#define CONF1_DA_MASK	0x00000380
18#define CONF1_DA_BASE	1
19#define CONF1_DL_SHIFT	10			/* D$ line size */
20#define CONF1_DL_MASK	0x00001c00
21#define CONF1_DL_BASE	2
22#define CONF1_DS_SHIFT	13			/* D$ sets/way */
23#define CONF1_DS_MASK	0x0000e000
24#define CONF1_DS_BASE	64
25#define CONF1_IA_SHIFT	16			/* I$ associativity */
26#define CONF1_IA_MASK	0x00070000
27#define CONF1_IA_BASE	1
28#define CONF1_IL_SHIFT	19			/* I$ line size */
29#define CONF1_IL_MASK	0x00380000
30#define CONF1_IL_BASE	2
31#define CONF1_IS_SHIFT	22			/* Instruction cache sets/way */
32#define CONF1_IS_MASK	0x01c00000
33#define CONF1_IS_BASE	64
34
35#define Index_Invalidate_I	0x00
36#define Index_Writeback_Inv_D   0x01
37
38	.text
39	LEAF(startup)
40	.set noreorder
41
42	/* Copy decompressor code to the right place */
43	li	t2, BZ_TEXT_START
44	add	a0, t2, 0
45	la      a1, code_start
46	la	a2, code_stop
47$L1:
48	lw	t0, 0(a1)
49	sw	t0, 0(a0)
50	add	a1, 4
51	add	a0, 4
52	blt	a1, a2, $L1
53	nop
54
55	/* At this point we need to invalidate dcache and */
56	/* icache before jumping to new code */
57
581:	/* Get cache sizes */
59	.set	mips32
60	mfc0	s0,C0_CONFIG,1
61	.set	mips0
62
63	li	s1,CONF1_DL_MASK
64	and	s1,s0
65	beq	s1,zero,nodc
66	nop
67
68	srl	s1,CONF1_DL_SHIFT
69	li	t0,CONF1_DL_BASE
70	sll	s1,t0,s1		/* s1 has D$ cache line size */
71
72	li	s2,CONF1_DA_MASK
73	and	s2,s0
74	srl	s2,CONF1_DA_SHIFT
75	addiu	s2,CONF1_DA_BASE	/* s2 now has D$ associativity */
76
77	li	t0,CONF1_DS_MASK
78	and	t0,s0
79	srl	t0,CONF1_DS_SHIFT
80	li	s3,CONF1_DS_BASE
81	sll	s3,s3,t0		/* s3 has D$ sets per way */
82
83	multu	s2,s3			/* sets/way * associativity */
84	mflo	t0			/* total cache lines */
85
86	multu	s1,t0			/* D$ linesize * lines */
87	mflo	s2			/* s2 is now D$ size in bytes */
88
89	/* Initilize the D$: */
90	mtc0	zero,C0_TAGLO
91	mtc0	zero,C0_TAGHI
92
93	li	t0,KSEG0		/* Just an address for the first $ line */
94	addu	t1,t0,s2		/*  + size of cache == end */
95
96	.set	mips3
971:	cache	Index_Writeback_Inv_D,0(t0)
98	.set	mips0
99	bne	t0,t1,1b
100	addu	t0,s1
101
102nodc:
103	/* Now we get to do it all again for the I$ */
104
105	move	s3,zero			/* just in case there is no icache */
106	move	s4,zero
107
108	li	t0,CONF1_IL_MASK
109	and	t0,s0
110	beq	t0,zero,noic
111	nop
112
113	srl	t0,CONF1_IL_SHIFT
114	li	s3,CONF1_IL_BASE
115	sll	s3,t0			/* s3 has I$ cache line size */
116
117	li	t0,CONF1_IA_MASK
118	and	t0,s0
119	srl	t0,CONF1_IA_SHIFT
120	addiu	s4,t0,CONF1_IA_BASE	/* s4 now has I$ associativity */
121
122	li	t0,CONF1_IS_MASK
123	and	t0,s0
124	srl	t0,CONF1_IS_SHIFT
125	li	s5,CONF1_IS_BASE
126	sll	s5,t0			/* s5 has I$ sets per way */
127
128	multu	s4,s5			/* sets/way * associativity */
129	mflo	t0			/* s4 is now total cache lines */
130
131	multu	s3,t0			/* I$ linesize * lines */
132	mflo	s4			/* s4 is cache size in bytes */
133
134	/* Initilize the I$: */
135	mtc0	zero,C0_TAGLO
136	mtc0	zero,C0_TAGHI
137
138	li	t0,KSEG0		/* Just an address for the first $ line */
139	addu	t1,t0,s4		/*  + size of cache == end */
140
141	.set	mips3
1421:	cache	Index_Invalidate_I,0(t0)
143	.set	mips0
144	bne	t0,t1,1b
145	addu	t0,s3
146
147noic:
148	move	a0,s3			/* icache line size */
149	move	a1,s4			/* icache size */
150	move	a2,s1			/* dcache line size */
151	jal	t2
152	move	a3,s2			/* dcache size */
153
154	.set reorder
155	END(startup)
156