powerpc/fsl-booke: Cleanup init/exception setup to be runtime

We currently have a few variants of fsl-booke processors (e500v1, e500v2,
e500mc, and e200).  They all have minor differences that we had previously
been handling via ifdefs.

To move towards having this support the following changes have been made:

* PID1, PID2 only exist on e500v1 & e500v2 and should not be accessed on
  e500mc or e200.  We use MMUCFG[NPIDS] to determine which case we are
  since we only touch PID1/2 in extremely early init code.

* Not all IVORs exist on all the processors so introduce cpu_setup
  functions for each variant to setup the proper IVORs that are either
  unique or exist but have some variations between the processors

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
Kumar Gala 2009-01-08 08:31:20 -06:00
parent 0585a155a7
commit 105c31df6f
6 changed files with 98 additions and 30 deletions

View File

@ -110,6 +110,7 @@
#define SPRN_L1CSR0 0x3F2 /* L1 Cache Control and Status Register 0 */ #define SPRN_L1CSR0 0x3F2 /* L1 Cache Control and Status Register 0 */
#define SPRN_L1CSR1 0x3F3 /* L1 Cache Control and Status Register 1 */ #define SPRN_L1CSR1 0x3F3 /* L1 Cache Control and Status Register 1 */
#define SPRN_MMUCSR0 0x3F4 /* MMU Control and Status Register 0 */ #define SPRN_MMUCSR0 0x3F4 /* MMU Control and Status Register 0 */
#define SPRN_MMUCFG 0x3F7 /* MMU Configuration Register */
#define SPRN_PIT 0x3DB /* Programmable Interval Timer */ #define SPRN_PIT 0x3DB /* Programmable Interval Timer */
#define SPRN_BUCSR 0x3F5 /* Branch Unit Control and Status */ #define SPRN_BUCSR 0x3F5 /* Branch Unit Control and Status */
#define SPRN_L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */ #define SPRN_L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */

View File

@ -61,6 +61,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \
obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x) += cpu_setup_44x.o obj-$(CONFIG_44x) += cpu_setup_44x.o
obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o
extra-$(CONFIG_PPC_STD_MMU) := head_32.o extra-$(CONFIG_PPC_STD_MMU) := head_32.o
extra-$(CONFIG_PPC64) := head_64.o extra-$(CONFIG_PPC64) := head_64.o

View File

@ -0,0 +1,31 @@
/*
* This file contains low level CPU setup functions.
* Kumar Gala <galak@kernel.crashing.org>
* Copyright 2009 Freescale Semiconductor, Inc.
*
* Based on cpu_setup_6xx code by
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
_GLOBAL(__setup_cpu_e200)
/* enable dedicated debug exception handling resources (Debug APU) */
mfspr r3,SPRN_HID0
ori r3,r3,HID0_DAPUEN@l
mtspr SPRN_HID0,r3
b __setup_e200_ivors
_GLOBAL(__setup_cpu_e500v1)
_GLOBAL(__setup_cpu_e500v2)
b __setup_e500_ivors
_GLOBAL(__setup_cpu_e500mc)
b __setup_e500mc_ivors

View File

@ -35,6 +35,10 @@ const char *powerpc_base_platform;
* and ppc64 * and ppc64
*/ */
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
extern void __setup_cpu_e200(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_e500mc(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
@ -1687,6 +1691,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
PPC_FEATURE_UNIFIED_CACHE, PPC_FEATURE_UNIFIED_CACHE,
.mmu_features = MMU_FTR_TYPE_FSL_E, .mmu_features = MMU_FTR_TYPE_FSL_E,
.dcache_bsize = 32, .dcache_bsize = 32,
.cpu_setup = __setup_cpu_e200,
.machine_check = machine_check_e200, .machine_check = machine_check_e200,
.platform = "ppc5554", .platform = "ppc5554",
} }
@ -1706,6 +1711,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.num_pmcs = 4, .num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500", .oprofile_cpu_type = "ppc/e500",
.oprofile_type = PPC_OPROFILE_FSL_EMB, .oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500v1,
.machine_check = machine_check_e500, .machine_check = machine_check_e500,
.platform = "ppc8540", .platform = "ppc8540",
}, },
@ -1724,6 +1730,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.num_pmcs = 4, .num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500", .oprofile_cpu_type = "ppc/e500",
.oprofile_type = PPC_OPROFILE_FSL_EMB, .oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500v2,
.machine_check = machine_check_e500, .machine_check = machine_check_e500,
.platform = "ppc8548", .platform = "ppc8548",
}, },
@ -1739,6 +1746,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.num_pmcs = 4, .num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */
.oprofile_type = PPC_OPROFILE_FSL_EMB, .oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500, .machine_check = machine_check_e500,
.platform = "ppce500mc", .platform = "ppce500mc",
}, },

View File

@ -70,10 +70,10 @@
/* only on e500mc/e200 */ /* only on e500mc/e200 */
#define DEBUG_STACK_BASE dbgirq_ctx #define DEBUG_STACK_BASE dbgirq_ctx
#ifdef CONFIG_PPC_E500MC #ifdef CONFIG_E200
#define DEBUG_SPRG SPRN_SPRG9
#else
#define DEBUG_SPRG SPRN_SPRG6W #define DEBUG_SPRG SPRN_SPRG6W
#else
#define DEBUG_SPRG SPRN_SPRG9
#endif #endif
#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE) #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)

View File

@ -103,10 +103,15 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4 or r7,r7,r4
mtspr SPRN_MAS6,r7 mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
#ifndef CONFIG_E200
mfspr r7,SPRN_MAS1 mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h andis. r7,r7,MAS1_VALID@h
bne match_TLB bne match_TLB
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne match_TLB /* skip if NPIDS != 3 */
mfspr r7,SPRN_PID1 mfspr r7,SPRN_PID1
slwi r7,r7,16 slwi r7,r7,16
or r7,r7,r4 or r7,r7,r4
@ -120,7 +125,7 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4 or r7,r7,r4
mtspr SPRN_MAS6,r7 mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* Fall through, we had to match */ tlbsx 0,r6 /* Fall through, we had to match */
#endif
match_TLB: match_TLB:
mfspr r7,SPRN_MAS0 mfspr r7,SPRN_MAS0
rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */ rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
@ -215,14 +220,19 @@ skpinv: addi r6,r6,1 /* Increment */
/* 4. Clear out PIDs & Search info */ /* 4. Clear out PIDs & Search info */
li r6,0 li r6,0
mtspr SPRN_MAS6,r6
mtspr SPRN_PID0,r6 mtspr SPRN_PID0,r6
#ifndef CONFIG_E200
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne 2f /* skip if NPIDS != 3 */
mtspr SPRN_PID1,r6 mtspr SPRN_PID1,r6
mtspr SPRN_PID2,r6 mtspr SPRN_PID2,r6
#endif
mtspr SPRN_MAS6,r6
/* 5. Invalidate mapping we started in */ /* 5. Invalidate mapping we started in */
2:
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7 mtspr SPRN_MAS0,r7
@ -298,19 +308,7 @@ skpinv: addi r6,r6,1 /* Increment */
SET_IVOR(12, WatchdogTimer); SET_IVOR(12, WatchdogTimer);
SET_IVOR(13, DataTLBError); SET_IVOR(13, DataTLBError);
SET_IVOR(14, InstructionTLBError); SET_IVOR(14, InstructionTLBError);
SET_IVOR(15, DebugDebug);
#if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC)
SET_IVOR(15, DebugCrit); SET_IVOR(15, DebugCrit);
#endif
SET_IVOR(32, SPEUnavailable);
SET_IVOR(33, SPEFloatingPointData);
SET_IVOR(34, SPEFloatingPointRound);
#ifndef CONFIG_E200
SET_IVOR(35, PerformanceMonitor);
#endif
#ifdef CONFIG_PPC_E500MC
SET_IVOR(36, Doorbell);
#endif
/* Establish the interrupt vector base */ /* Establish the interrupt vector base */
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
@ -329,12 +327,6 @@ skpinv: addi r6,r6,1 /* Increment */
oris r2,r2,HID0_DOZE@h oris r2,r2,HID0_DOZE@h
mtspr SPRN_HID0, r2 mtspr SPRN_HID0, r2
#endif #endif
#ifdef CONFIG_E200
/* enable dedicated debug exception handling resources (Debug APU) */
mfspr r2,SPRN_HID0
ori r2,r2,HID0_DAPUEN@l
mtspr SPRN_HID0,r2
#endif
#if !defined(CONFIG_BDI_SWITCH) #if !defined(CONFIG_BDI_SWITCH)
/* /*
@ -706,15 +698,11 @@ interrupt_base:
/* Performance Monitor */ /* Performance Monitor */
EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
#ifdef CONFIG_PPC_E500MC
EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD) EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD)
#endif
/* Debug Interrupt */ /* Debug Interrupt */
DEBUG_DEBUG_EXCEPTION DEBUG_DEBUG_EXCEPTION
#if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC)
DEBUG_CRIT_EXCEPTION DEBUG_CRIT_EXCEPTION
#endif
/* /*
* Local functions * Local functions
@ -897,6 +885,45 @@ KernelSPE:
* Global functions * Global functions
*/ */
/* Adjust or setup IVORs for e200 */
_GLOBAL(__setup_e200_ivors)
li r3,DebugDebug@l
mtspr SPRN_IVOR15,r3
li r3,SPEUnavailable@l
mtspr SPRN_IVOR32,r3
li r3,SPEFloatingPointData@l
mtspr SPRN_IVOR33,r3
li r3,SPEFloatingPointRound@l
mtspr SPRN_IVOR34,r3
sync
blr
/* Adjust or setup IVORs for e500v1/v2 */
_GLOBAL(__setup_e500_ivors)
li r3,DebugCrit@l
mtspr SPRN_IVOR15,r3
li r3,SPEUnavailable@l
mtspr SPRN_IVOR32,r3
li r3,SPEFloatingPointData@l
mtspr SPRN_IVOR33,r3
li r3,SPEFloatingPointRound@l
mtspr SPRN_IVOR34,r3
li r3,PerformanceMonitor@l
mtspr SPRN_IVOR35,r3
sync
blr
/* Adjust or setup IVORs for e500mc */
_GLOBAL(__setup_e500mc_ivors)
li r3,DebugDebug@l
mtspr SPRN_IVOR15,r3
li r3,PerformanceMonitor@l
mtspr SPRN_IVOR35,r3
li r3,Doorbell@l
mtspr SPRN_IVOR36,r3
sync
blr
/* /*
* extern void loadcam_entry(unsigned int index) * extern void loadcam_entry(unsigned int index)
* *