aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/mach-pnx8550/kernel-entry-init.h
blob: 982079f410b5b5bf13328da323ae8f7e2e321d48 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2005 Embedded Alley Solutions, Inc
 */
#ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H
#define __ASM_MACH_KERNEL_ENTRY_INIT_H

#include <asm/cacheops.h>
#include <asm/addrspace.h>

#define CO_CONFIGPR_VALID  0x3F1F41FF    /* valid bits to write to ConfigPR */
#define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;
#define CACHE_OPC      0xBC000000  /* MIPS cache instruction opcode */
#define ICACHE_LINE_SIZE        32      /* Instruction cache line size bytes */
#define DCACHE_LINE_SIZE        32      /* Data cache line size in bytes */

#define ICACHE_SET_COUNT        256     /* Instruction cache set count */
#define DCACHE_SET_COUNT        128     /* Data cache set count */

#define ICACHE_SET_SIZE         (ICACHE_SET_COUNT * ICACHE_LINE_SIZE)
#define DCACHE_SET_SIZE         (DCACHE_SET_COUNT * DCACHE_LINE_SIZE)

	.macro	kernel_entry_setup
	.set	push
	.set	noreorder
	/*
	 * PNX8550 entry point, when running a non compressed
	 * kernel. When loading a zImage, the head.S code in
	 * arch/mips/zboot/pnx8550 will init the caches and,
	 * decompress the kernel, and branch to kernel_entry.
		 */
cache_begin:	li	t0, (1<<28)
	mtc0	t0, CP0_STATUS /* cp0 usable */
	HAZARD_CP0

	mtc0 	zero, CP0_CAUSE
	HAZARD_CP0


	/* Set static virtual to phys address translation and TLB disabled */
	mfc0 	t0, CP0_CONFIG, 7
	HAZARD_CP0

	and t0,~((1<<19) | (1<<20))     /* TLB/MAP cleared */
	mtc0	t0, CP0_CONFIG, 7
	HAZARD_CP0

	/* CPU boots with kseg0 cache algo set to 0x2 -- uncached */

	init_icache
	nop
	init_dcache
	nop

	cachePr4450ICReset
	nop

	cachePr4450DCReset
	nop

	/* read ConfigPR into t0 */
	mfc0	t0, CP0_CONFIG, 7
	HAZARD_CP0

	/*  enable the TLB */
	or      t0, (1<<19)

	/* disable the ICACHE: at least 10x slower */
	/* or      t0, (1<<26) */

	/* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set  */
	/* or      t0, (1<<27) */

	and	t0, CO_CONFIGPR_VALID

	/* enable TLB. */
	mtc0	t0, CP0_CONFIG, 7
	HAZARD_CP0
cache_end:
	/* Setup CMEM_0 to MMIO address space, 2MB */
	lui    t0, 0x1BE0
	addi   t0, t0, 0x3
	mtc0   $8, $22, 4
	nop

	/* Setup CMEM_1, 128MB */
	lui    t0, 0x1000
	addi   t0, t0, 0xf
	mtc0   $8, $22, 5
	nop


	/* Setup CMEM_2, 32MB */
	lui    t0, 0x1C00
	addi   t0, t0, 0xb
	mtc0   $8, $22, 6
	nop

	/* Setup CMEM_3, 0MB */
	lui    t0, 0x0
	addi   t0, t0, 0x0
	mtc0   $8, $22, 7
	nop

	/* Enable cache */
	mfc0	t0, CP0_CONFIG
	HAZARD_CP0
	and	t0, t0, 0xFFFFFFF8
	or	t0, t0, 3
	mtc0	t0, CP0_CONFIG
	HAZARD_CP0
	.set	pop
	.endm

	.macro	init_icache
	.set	push
	.set	noreorder

	/* Get Cache Configuration */
	mfc0	t3, CP0_CONFIG, 1
	HAZARD_CP0

	/* get cache Line size */

	srl   t1, t3, 19   /* C0_CONFIGPR_IL_SHIFT */
	andi  t1, t1, 0x7  /* C0_CONFIGPR_IL_MASK */
	beq   t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */
	nop
	addiu t0, t1, 1
	ori   t1, zero, 1
	sllv  t1, t1, t0

	/* get max cache Index */
	srl   t2, t3, 22  /* C0_CONFIGPR_IS_SHIFT */
	andi  t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */
	addiu t0, t2, 6
	ori   t2, zero, 1
	sllv  t2, t2, t0

	/* get max cache way */
	srl   t3, t3, 16  /* C0_CONFIGPR_IA_SHIFT */
	andi  t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */
	addiu t3, t3, 1

	/* total no of cache lines */
	multu t2, t3             /* max index * max way */
	mflo  t2
	addiu t2, t2, -1

	move  t0, zero
pr4450_next_instruction_cache_set:
	cache  Index_Invalidate_I, 0(t0)
	addu  t0, t0, t1         /* add bytes in a line */
	bne   t2, zero, pr4450_next_instruction_cache_set
	addiu t2, t2, -1   /* reduce no of lines to invalidate by one */
pr4450_instr_cache_invalidated:
	.set	pop
	.endm

	.macro	init_dcache
	.set	push
	.set	noreorder
	move t1, zero

	/* Store Tag Information */
	mtc0	zero, CP0_TAGLO, 0
	HAZARD_CP0

	mtc0	zero, CP0_TAGHI, 0
	HAZARD_CP0

	/* Cache size is 16384 = 512 lines x 32 bytes per line */
	or       t2, zero, (128*4)-1  /* 512 lines  */
	/* Invalidate all lines */
2:
	cache Index_Store_Tag_D, 0(t1)
	addiu    t2, t2, -1
	bne      t2, zero, 2b
	addiu    t1, t1, 32        /* 32 bytes in a line */
	.set pop
	.endm

	.macro	cachePr4450ICReset
	.set	push
	.set	noreorder

	/* Save CP0 status reg on entry; */
	/* disable interrupts during cache reset */
	mfc0    t0, CP0_STATUS      /* T0 = interrupt status on entry */
	HAZARD_CP0

	mtc0    zero, CP0_STATUS   /* disable CPU interrupts */
	HAZARD_CP0

	or      t1, zero, zero              /* T1 = starting cache index (0) */
	ori     t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */

	icache_invd_loop:
	/* 9 == register t1 */
	.word   CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
		(0 * ICACHE_SET_SIZE)  /* invalidate inst cache WAY0 */
	.word   CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
		(1 * ICACHE_SET_SIZE)  /* invalidate inst cache WAY1 */

	addiu   t1, t1, ICACHE_LINE_SIZE    /* T1 = next cache line index */
	bne     t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */
	addiu   t2, t2, -1        /* decrement T2 set cnt (delay slot) */

	/* Initialize the latches in the instruction cache tag */
	/* that drive the way selection tri-state bus drivers, by doing a */
	/* dummy load while the instruction cache is still disabled. */
	/* TODO: Is this needed ? */
	la      t1, KSEG0            /* T1 = cached memory base address */
	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */

	mtc0    t0, CP0_STATUS        /* restore interrupt status on entry */
	HAZARD_CP0
	.set	pop
	.endm

	.macro	cachePr4450DCReset
	.set	push
	.set	noreorder
	mfc0    t0, CP0_STATUS           /* T0 = interrupt status on entry */
	HAZARD_CP0
	mtc0    zero, CP0_STATUS         /* disable CPU interrupts */
	HAZARD_CP0

	/* Writeback/invalidate entire data cache sets/ways/lines */
	or      t1, zero, zero              /* T1 = starting cache index (0) */
	ori     t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */

	dcache_wbinvd_loop:
	/* 9 == register t1 */
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
		(0 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY0 */
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
		(1 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY1 */
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
		(2 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY2 */
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
		(3 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY3 */

	addiu   t1, t1, DCACHE_LINE_SIZE  /* T1 = next data cache line index */
	bne     t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */
	addiu   t2, t2, -1          /* decrement T2 set cnt (delay slot) */

	/* Initialize the latches in the data cache tag that drive the way
	selection tri-state bus drivers, by doing a dummy load while the
	data cache is still in the disabled mode.  TODO: Is this needed ? */
	la      t1, KSEG0            /* T1 = cached memory base address */
	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */

	mtc0    t0, CP0_STATUS       /* restore interrupt status on entry */
	HAZARD_CP0
	.set	pop
	.endm

#endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */