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 */
|