diff options
author | Sam Ravnborg <sam@ravnborg.org> | 2012-05-25 17:20:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-28 02:52:41 -0400 |
commit | 7b372d6582ca3bf41a1af9f168f3a852f3d7b21d (patch) | |
tree | 3a3269b976d713dd728b119e388f8f262c533138 | |
parent | ec24158eac0ae2786ebf1e0afa8f3664891319ba (diff) |
sparc32: implement proper LEON support in head_32 (before highmem)
Use PSR to check if the CPU is LEON and jump to
LEON specific code in this case.
Added a few constants to psr.h to increase readability.
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Daniel Hellstrom <daniel@gaisler.com>
Cc: Konrad Eisele <konrad@gaisler.com>
-rw-r--r-- | arch/sparc/include/asm/psr.h | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/head_32.S | 58 |
2 files changed, 53 insertions, 11 deletions
diff --git a/arch/sparc/include/asm/psr.h b/arch/sparc/include/asm/psr.h index b8c0e5f0a66b..c02c735d4ebe 100644 --- a/arch/sparc/include/asm/psr.h +++ b/arch/sparc/include/asm/psr.h | |||
@@ -35,6 +35,12 @@ | |||
35 | #define PSR_VERS 0x0f000000 /* cpu-version field */ | 35 | #define PSR_VERS 0x0f000000 /* cpu-version field */ |
36 | #define PSR_IMPL 0xf0000000 /* cpu-implementation field */ | 36 | #define PSR_IMPL 0xf0000000 /* cpu-implementation field */ |
37 | 37 | ||
38 | #define PSR_IMPL_SHIFT 28 | ||
39 | #define PSR_IMPL_SHIFTED_MASK 0xf | ||
40 | |||
41 | #define PSR_IMPL_TI 0x4 | ||
42 | #define PSR_IMPL_LEON 0xf | ||
43 | |||
38 | #ifdef __KERNEL__ | 44 | #ifdef __KERNEL__ |
39 | 45 | ||
40 | #ifndef __ASSEMBLY__ | 46 | #ifndef __ASSEMBLY__ |
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 693fb080f933..5a418d32d94c 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S | |||
@@ -192,7 +192,7 @@ copy_prom_done: | |||
192 | bne not_a_sun4 | 192 | bne not_a_sun4 |
193 | nop | 193 | nop |
194 | 194 | ||
195 | halt_sun4_or_sun4c: | 195 | halt_notsup: |
196 | ld [%g7 + 0x68], %o1 | 196 | ld [%g7 + 0x68], %o1 |
197 | set notsup, %o0 | 197 | set notsup, %o0 |
198 | sub %o0, %l6, %o0 | 198 | sub %o0, %l6, %o0 |
@@ -202,18 +202,31 @@ halt_sun4_or_sun4c: | |||
202 | nop | 202 | nop |
203 | 203 | ||
204 | not_a_sun4: | 204 | not_a_sun4: |
205 | /* It looks like this is a machine we support. | ||
206 | * Now find out what MMU we are dealing with | ||
207 | * LEON - identified by the psr.impl field | ||
208 | * Viking - identified by the psr.impl field | ||
209 | * In all other cases a sun4m srmmu. | ||
210 | * We check that the MMU is enabled in all cases. | ||
211 | */ | ||
212 | |||
213 | /* Check if this is a LEON CPU */ | ||
214 | rd %psr, %g3 | ||
215 | srl %g3, PSR_IMPL_SHIFT, %g3 | ||
216 | and %g3, PSR_IMPL_SHIFTED_MASK, %g3 | ||
217 | cmp %g3, PSR_IMPL_LEON | ||
218 | be leon_remap /* It is a LEON - jump */ | ||
219 | nop | ||
220 | |||
221 | /* Sanity-check, is MMU enabled */ | ||
205 | lda [%g0] ASI_M_MMUREGS, %g1 | 222 | lda [%g0] ASI_M_MMUREGS, %g1 |
206 | andcc %g1, 1, %g0 | 223 | andcc %g1, 1, %g0 |
207 | be halt_sun4_or_sun4c | 224 | be halt_notsup |
208 | nop | 225 | nop |
209 | 226 | ||
210 | srmmu_remap: | 227 | /* Check for a viking (TI) module. */ |
211 | /* First, check for a viking (TI) module. */ | 228 | cmp %g3, PSR_IMPL_TI |
212 | set 0x40000000, %g2 | 229 | bne srmmu_not_viking |
213 | rd %psr, %g3 | ||
214 | and %g2, %g3, %g3 | ||
215 | subcc %g3, 0x0, %g0 | ||
216 | bz srmmu_nviking | ||
217 | nop | 230 | nop |
218 | 231 | ||
219 | /* Figure out what kind of viking we are on. | 232 | /* Figure out what kind of viking we are on. |
@@ -228,7 +241,7 @@ srmmu_remap: | |||
228 | lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg | 241 | lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg |
229 | and %g2, %g3, %g3 | 242 | and %g2, %g3, %g3 |
230 | subcc %g3, 0x0, %g0 | 243 | subcc %g3, 0x0, %g0 |
231 | bnz srmmu_nviking ! is in mbus mode | 244 | bnz srmmu_not_viking ! is in mbus mode |
232 | nop | 245 | nop |
233 | 246 | ||
234 | rd %psr, %g3 ! DO NOT TOUCH %g3 | 247 | rd %psr, %g3 ! DO NOT TOUCH %g3 |
@@ -293,12 +306,12 @@ srmmu_remap: | |||
293 | b go_to_highmem | 306 | b go_to_highmem |
294 | nop | 307 | nop |
295 | 308 | ||
309 | srmmu_not_viking: | ||
296 | /* This works on viking's in Mbus mode and all | 310 | /* This works on viking's in Mbus mode and all |
297 | * other MBUS modules. It is virtually the same as | 311 | * other MBUS modules. It is virtually the same as |
298 | * the above madness sans turning traps off and flipping | 312 | * the above madness sans turning traps off and flipping |
299 | * the AC bit. | 313 | * the AC bit. |
300 | */ | 314 | */ |
301 | srmmu_nviking: | ||
302 | set AC_M_CTPR, %g1 | 315 | set AC_M_CTPR, %g1 |
303 | lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr | 316 | lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr |
304 | sll %g1, 0x4, %g1 ! make physical addr | 317 | sll %g1, 0x4, %g1 ! make physical addr |
@@ -313,6 +326,29 @@ srmmu_nviking: | |||
313 | nop ! wheee.... | 326 | nop ! wheee.... |
314 | 327 | ||
315 | 328 | ||
329 | leon_remap: | ||
330 | /* Sanity-check, is MMU enabled */ | ||
331 | lda [%g0] ASI_LEON_MMUREGS, %g1 | ||
332 | andcc %g1, 1, %g0 | ||
333 | be halt_notsup | ||
334 | nop | ||
335 | |||
336 | /* Same code as in the srmmu_not_viking case, | ||
337 | * with the LEON ASI for mmuregs | ||
338 | */ | ||
339 | set AC_M_CTPR, %g1 | ||
340 | lda [%g1] ASI_LEON_MMUREGS, %g1 ! get ctx table ptr | ||
341 | sll %g1, 0x4, %g1 ! make physical addr | ||
342 | lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table | ||
343 | srl %g1, 0x4, %g1 | ||
344 | sll %g1, 0x8, %g1 ! make phys addr for l1 tbl | ||
345 | |||
346 | lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0 | ||
347 | add %g1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %g3 | ||
348 | sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry | ||
349 | b go_to_highmem | ||
350 | nop ! wheee.... | ||
351 | |||
316 | /* Now do a non-relative jump so that PC is in high-memory */ | 352 | /* Now do a non-relative jump so that PC is in high-memory */ |
317 | go_to_highmem: | 353 | go_to_highmem: |
318 | set execute_in_high_mem, %g1 | 354 | set execute_in_high_mem, %g1 |