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	addi    sp, -48
42	sw      a0, 16(sp)
43	sw      a1, 20(sp)
44	sw      a2, 24(sp)
45	sw      a3, 28(sp)
46
47	/* Copy decompressor code to the right place */
48	li	t2, BZ_TEXT_START
49	add	a0, t2, 0
50	la      a1, code_start
51	la	a2, code_stop
52$L1:
53	lw	t0, 0(a1)
54	sw	t0, 0(a0)
55	add	a1, 4
56	add	a0, 4
57	blt	a1, a2, $L1
58	nop
59
60	/* At this point we need to invalidate dcache and */
61	/* icache before jumping to new code */
62
631:	/* Get cache sizes */
64	.set	mips32
65	mfc0	s0,C0_CONFIG,1
66	.set	mips0
67
68	li	s1,CONF1_DL_MASK
69	and	s1,s0
70	beq	s1,zero,nodc
71	nop
72
73	srl	s1,CONF1_DL_SHIFT
74	li	t0,CONF1_DL_BASE
75	sll	s1,t0,s1		/* s1 has D$ cache line size */
76
77	li	s2,CONF1_DA_MASK
78	and	s2,s0
79	srl	s2,CONF1_DA_SHIFT
80	addiu	s2,CONF1_DA_BASE	/* s2 now has D$ associativity */
81
82	li	t0,CONF1_DS_MASK
83	and	t0,s0
84	srl	t0,CONF1_DS_SHIFT
85	li	s3,CONF1_DS_BASE
86	sll	s3,s3,t0		/* s3 has D$ sets per way */
87
88	multu	s2,s3			/* sets/way * associativity */
89	mflo	t0			/* total cache lines */
90
91	multu	s1,t0			/* D$ linesize * lines */
92	mflo	s2			/* s2 is now D$ size in bytes */
93
94	/* Initilize the D$: */
95	mtc0	zero,C0_TAGLO
96	mtc0	zero,C0_TAGHI
97
98	li	t0,KSEG0		/* Just an address for the first $ line */
99	addu	t1,t0,s2		/*  + size of cache == end */
100
101	.set	mips3
1021:	cache	Index_Writeback_Inv_D,0(t0)
103	.set	mips0
104	bne	t0,t1,1b
105	addu	t0,s1
106
107nodc:
108	/* Now we get to do it all again for the I$ */
109
110	move	s3,zero			/* just in case there is no icache */
111	move	s4,zero
112
113	li	t0,CONF1_IL_MASK
114	and	t0,s0
115	beq	t0,zero,noic
116	nop
117
118	srl	t0,CONF1_IL_SHIFT
119	li	s3,CONF1_IL_BASE
120	sll	s3,t0			/* s3 has I$ cache line size */
121
122	li	t0,CONF1_IA_MASK
123	and	t0,s0
124	srl	t0,CONF1_IA_SHIFT
125	addiu	s4,t0,CONF1_IA_BASE	/* s4 now has I$ associativity */
126
127	li	t0,CONF1_IS_MASK
128	and	t0,s0
129	srl	t0,CONF1_IS_SHIFT
130	li	s5,CONF1_IS_BASE
131	sll	s5,t0			/* s5 has I$ sets per way */
132
133	multu	s4,s5			/* sets/way * associativity */
134	mflo	t0			/* s4 is now total cache lines */
135
136	multu	s3,t0			/* I$ linesize * lines */
137	mflo	s4			/* s4 is cache size in bytes */
138
139	/* Initilize the I$: */
140	mtc0	zero,C0_TAGLO
141	mtc0	zero,C0_TAGHI
142
143	li	t0,KSEG0		/* Just an address for the first $ line */
144	addu	t1,t0,s4		/*  + size of cache == end */
145
146	.set	mips3
1471:	cache	Index_Invalidate_I,0(t0)
148	.set	mips0
149	bne	t0,t1,1b
150	addu	t0,s3
151
152noic:
153	move	a0,s4			/* icache size */
154	move	a1,s3			/* icache line size */
155	move	a2,s2			/* dcache size */
156	jal	t2
157	move	a3,s1			/* dcache line size */
158
159	.set reorder
160	END(startup)
161