1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Embedded Alley Solutions, Inc
7 */
8#ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H
9#define __ASM_MACH_KERNEL_ENTRY_INIT_H
10
11#include <asm/cacheops.h>
12#include <asm/addrspace.h>
13
14#define CO_CONFIGPR_VALID  0x3F1F41FF    /* valid bits to write to ConfigPR */
15#define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;
16#define CACHE_OPC      0xBC000000  /* MIPS cache instruction opcode */
17#define ICACHE_LINE_SIZE        32      /* Instruction cache line size bytes */
18#define DCACHE_LINE_SIZE        32      /* Data cache line size in bytes */
19
20#define ICACHE_SET_COUNT        256     /* Instruction cache set count */
21#define DCACHE_SET_COUNT        128     /* Data cache set count */
22
23#define ICACHE_SET_SIZE         (ICACHE_SET_COUNT * ICACHE_LINE_SIZE)
24#define DCACHE_SET_SIZE         (DCACHE_SET_COUNT * DCACHE_LINE_SIZE)
25
26	.macro	kernel_entry_setup
27	.set	push
28	.set	noreorder
29	/*
30	 * PNX8550 entry point, when running a non compressed
31	 * kernel. When loading a zImage, the head.S code in
32	 * arch/mips/zboot/pnx8550 will init the caches and,
33	 * decompress the kernel, and branch to kernel_entry.
34		 */
35cache_begin:	li	t0, (1<<28)
36	mtc0	t0, CP0_STATUS /* cp0 usable */
37	HAZARD_CP0
38
39	mtc0 	zero, CP0_CAUSE
40	HAZARD_CP0
41
42
43	/* Set static virtual to phys address translation and TLB disabled */
44	mfc0 	t0, CP0_CONFIG, 7
45	HAZARD_CP0
46
47	and t0,~((1<<19) | (1<<20))     /* TLB/MAP cleared */
48	mtc0	t0, CP0_CONFIG, 7
49	HAZARD_CP0
50
51	/* CPU boots with kseg0 cache algo set to 0x2 -- uncached */
52
53	init_icache
54	nop
55	init_dcache
56	nop
57
58	cachePr4450ICReset
59	nop
60
61	cachePr4450DCReset
62	nop
63
64	/* read ConfigPR into t0 */
65	mfc0	t0, CP0_CONFIG, 7
66	HAZARD_CP0
67
68	/*  enable the TLB */
69	or      t0, (1<<19)
70
71	/* disable the ICACHE: at least 10x slower */
72	/* or      t0, (1<<26) */
73
74	/* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set  */
75	/* or      t0, (1<<27) */
76
77	and	t0, CO_CONFIGPR_VALID
78
79	/* enable TLB. */
80	mtc0	t0, CP0_CONFIG, 7
81	HAZARD_CP0
82cache_end:
83	/* Setup CMEM_0 to MMIO address space, 2MB */
84	lui    t0, 0x1BE0
85	addi   t0, t0, 0x3
86	mtc0   $8, $22, 4
87	nop
88
89	/* Setup CMEM_1, 128MB */
90	lui    t0, 0x1000
91	addi   t0, t0, 0xf
92	mtc0   $8, $22, 5
93	nop
94
95
96	/* Setup CMEM_2, 32MB */
97	lui    t0, 0x1C00
98	addi   t0, t0, 0xb
99	mtc0   $8, $22, 6
100	nop
101
102	/* Setup CMEM_3, 0MB */
103	lui    t0, 0x0
104	addi   t0, t0, 0x0
105	mtc0   $8, $22, 7
106	nop
107
108	/* Enable cache */
109	mfc0	t0, CP0_CONFIG
110	HAZARD_CP0
111	and	t0, t0, 0xFFFFFFF8
112	or	t0, t0, 3
113	mtc0	t0, CP0_CONFIG
114	HAZARD_CP0
115	.set	pop
116	.endm
117
118	.macro	init_icache
119	.set	push
120	.set	noreorder
121
122	/* Get Cache Configuration */
123	mfc0	t3, CP0_CONFIG, 1
124	HAZARD_CP0
125
126	/* get cache Line size */
127
128	srl   t1, t3, 19   /* C0_CONFIGPR_IL_SHIFT */
129	andi  t1, t1, 0x7  /* C0_CONFIGPR_IL_MASK */
130	beq   t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */
131	nop
132	addiu t0, t1, 1
133	ori   t1, zero, 1
134	sllv  t1, t1, t0
135
136	/* get max cache Index */
137	srl   t2, t3, 22  /* C0_CONFIGPR_IS_SHIFT */
138	andi  t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */
139	addiu t0, t2, 6
140	ori   t2, zero, 1
141	sllv  t2, t2, t0
142
143	/* get max cache way */
144	srl   t3, t3, 16  /* C0_CONFIGPR_IA_SHIFT */
145	andi  t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */
146	addiu t3, t3, 1
147
148	/* total no of cache lines */
149	multu t2, t3             /* max index * max way */
150	mflo  t2
151	addiu t2, t2, -1
152
153	move  t0, zero
154pr4450_next_instruction_cache_set:
155	cache  Index_Invalidate_I, 0(t0)
156	addu  t0, t0, t1         /* add bytes in a line */
157	bne   t2, zero, pr4450_next_instruction_cache_set
158	addiu t2, t2, -1   /* reduce no of lines to invalidate by one */
159pr4450_instr_cache_invalidated:
160	.set	pop
161	.endm
162
163	.macro	init_dcache
164	.set	push
165	.set	noreorder
166	move t1, zero
167
168	/* Store Tag Information */
169	mtc0	zero, CP0_TAGLO, 0
170	HAZARD_CP0
171
172	mtc0	zero, CP0_TAGHI, 0
173	HAZARD_CP0
174
175	/* Cache size is 16384 = 512 lines x 32 bytes per line */
176	or       t2, zero, (128*4)-1  /* 512 lines  */
177	/* Invalidate all lines */
1782:
179	cache Index_Store_Tag_D, 0(t1)
180	addiu    t2, t2, -1
181	bne      t2, zero, 2b
182	addiu    t1, t1, 32        /* 32 bytes in a line */
183	.set pop
184	.endm
185
186	.macro	cachePr4450ICReset
187	.set	push
188	.set	noreorder
189
190	/* Save CP0 status reg on entry; */
191	/* disable interrupts during cache reset */
192	mfc0    t0, CP0_STATUS      /* T0 = interrupt status on entry */
193	HAZARD_CP0
194
195	mtc0    zero, CP0_STATUS   /* disable CPU interrupts */
196	HAZARD_CP0
197
198	or      t1, zero, zero              /* T1 = starting cache index (0) */
199	ori     t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */
200
201	icache_invd_loop:
202	/* 9 == register t1 */
203	.word   (CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
204		(0 * ICACHE_SET_SIZE))  /* invalidate inst cache WAY0 */
205	.word   (CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
206		(1 * ICACHE_SET_SIZE))  /* invalidate inst cache WAY1 */
207
208	addiu   t1, t1, ICACHE_LINE_SIZE    /* T1 = next cache line index */
209	bne     t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */
210	addiu   t2, t2, -1        /* decrement T2 set cnt (delay slot) */
211
212	/* Initialize the latches in the instruction cache tag */
213	/* that drive the way selection tri-state bus drivers, by doing a */
214	/* dummy load while the instruction cache is still disabled. */
215	/* TODO: Is this needed ? */
216	la      t1, KSEG0            /* T1 = cached memory base address */
217	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
218
219	mtc0    t0, CP0_STATUS        /* restore interrupt status on entry */
220	HAZARD_CP0
221	.set	pop
222	.endm
223
224	.macro	cachePr4450DCReset
225	.set	push
226	.set	noreorder
227	mfc0    t0, CP0_STATUS           /* T0 = interrupt status on entry */
228	HAZARD_CP0
229	mtc0    zero, CP0_STATUS         /* disable CPU interrupts */
230	HAZARD_CP0
231
232	/* Writeback/invalidate entire data cache sets/ways/lines */
233	or      t1, zero, zero              /* T1 = starting cache index (0) */
234	ori     t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */
235
236	dcache_wbinvd_loop:
237	/* 9 == register t1 */
238	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
239		(0 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY0 */
240	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
241		(1 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY1 */
242	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
243		(2 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY2 */
244	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
245		(3 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY3 */
246
247	addiu   t1, t1, DCACHE_LINE_SIZE  /* T1 = next data cache line index */
248	bne     t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */
249	addiu   t2, t2, -1          /* decrement T2 set cnt (delay slot) */
250
251	/* Initialize the latches in the data cache tag that drive the way
252	selection tri-state bus drivers, by doing a dummy load while the
253	data cache is still in the disabled mode.  TODO: Is this needed ? */
254	la      t1, KSEG0            /* T1 = cached memory base address */
255	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
256
257	mtc0    t0, CP0_STATUS       /* restore interrupt status on entry */
258	HAZARD_CP0
259	.set	pop
260	.endm
261
262#endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */
263