Skip to content

Commit

Permalink
[PATCH] ppc32: Add support for Freescale e200 (Book-E) core
Browse files Browse the repository at this point in the history
The e200 core is a Book-E core (similar to e500) that has a unified L1 cache
and is not cache coherent on the bus.  The e200 core also adds a separate
exception level for debug exceptions.  Part of this patch helps to cleanup a
few cases that are true for all Freescale Book-E parts, not just e500.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Kumar Gala authored and Linus Torvalds committed Jun 25, 2005
1 parent 62aa751 commit 33d9e9b
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 18 deletions.
17 changes: 10 additions & 7 deletions arch/ppc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ config 8xx
depends on BROKEN
bool "8xx"

config E200
bool "e200"

config E500
bool "e500"

Expand All @@ -98,12 +101,12 @@ config PPC_FPU

config BOOKE
bool
depends on E500
depends on E200 || E500
default y

config FSL_BOOKE
bool
depends on E500
depends on E200 || E500
default y

config PTE_64BIT
Expand Down Expand Up @@ -141,16 +144,16 @@ config ALTIVEC

config SPE
bool "SPE Support"
depends on E500
depends on E200 || E500
---help---
This option enables kernel support for the Signal Processing
Extensions (SPE) to the PowerPC processor. The kernel currently
supports saving and restoring SPE registers, and turning on the
'spe enable' bit so user processes can execute SPE instructions.

This option is only usefully if you have a processor that supports
This option is only useful if you have a processor that supports
SPE (e500, otherwise known as 85xx series), but does not have any
affect on a non-spe cpu (it does, however add code to the kernel).
effect on a non-spe cpu (it does, however add code to the kernel).

If in doubt, say Y here.

Expand Down Expand Up @@ -200,7 +203,7 @@ config TAU_AVERAGE

config MATH_EMULATION
bool "Math emulation"
depends on 4xx || 8xx || E500
depends on 4xx || 8xx || E200 || E500
---help---
Some PowerPC chips designed for embedded applications do not have
a floating-point unit and therefore do not implement the
Expand Down Expand Up @@ -254,7 +257,7 @@ config PPC_STD_MMU

config NOT_COHERENT_CACHE
bool
depends on 4xx || 8xx
depends on 4xx || 8xx || E200
default y

endmenu
Expand Down
3 changes: 2 additions & 1 deletion arch/ppc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CPP = $(CC) -E $(CFLAGS)

CHECKFLAGS += -D__powerpc__

ifndef CONFIG_E500
ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif

Expand All @@ -38,6 +38,7 @@ cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200

AFLAGS += $(cpu-as-y)
CFLAGS += $(cpu-as-y)
Expand Down
2 changes: 2 additions & 0 deletions arch/ppc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
obj-$(CONFIG_TAU) += temp.o
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
ifndef CONFIG_E200
obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
endif

ifndef CONFIG_MATH_EMULATION
obj-$(CONFIG_8xx) += softemu8xx.o
Expand Down
25 changes: 24 additions & 1 deletion arch/ppc/kernel/cputable.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,30 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
},
#endif /* CONFIG_44x */
#ifdef CONFIG_E500
#ifdef CONFIG_FSL_BOOKE
{ /* e200z5 */
.pvr_mask = 0xfff00000,
.pvr_value = 0x81000000,
.cpu_name = "e200z5",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTR_USE_TB,
.cpu_user_features = PPC_FEATURE_32 |
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
},
{ /* e200z6 */
.pvr_mask = 0xfff00000,
.pvr_value = 0x81100000,
.cpu_name = "e200z6",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTR_USE_TB,
.cpu_user_features = PPC_FEATURE_32 |
PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
},
{ /* e500 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x80200000,
Expand Down
9 changes: 9 additions & 0 deletions arch/ppc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ mcheck_transfer_to_handler:
TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
b transfer_to_handler_full

.globl debug_transfer_to_handler
debug_transfer_to_handler:
TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
b transfer_to_handler_full

.globl crit_transfer_to_handler
crit_transfer_to_handler:
TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
Expand Down Expand Up @@ -835,6 +840,10 @@ ret_from_crit_exc:
RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)

#ifdef CONFIG_BOOKE
.globl ret_from_debug_exc
ret_from_debug_exc:
RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)

.globl ret_from_mcheck_exc
ret_from_mcheck_exc:
RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
Expand Down
64 changes: 63 additions & 1 deletion arch/ppc/kernel/head_booke.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
*
* On 40x critical is the only additional level
* On 44x/e500 we have critical and machine check
* On e200 we have critical and debug (machine check occurs via critical)
*
* Additionally we reserve a SPRG for each priority level so we can free up a
* GPR to use as the base for indirect access to the exception stacks. This
Expand All @@ -60,12 +61,16 @@

/* CRIT_SPRG only used in critical exception handling */
#define CRIT_SPRG SPRN_SPRG2
/* MCHECK_SPRG only used in critical exception handling */
/* MCHECK_SPRG only used in machine check exception handling */
#define MCHECK_SPRG SPRN_SPRG6W

#define MCHECK_STACK_TOP (exception_stack_top - 4096)
#define CRIT_STACK_TOP (exception_stack_top)

/* only on e200 for now */
#define DEBUG_STACK_TOP (exception_stack_top - 4096)
#define DEBUG_SPRG SPRN_SPRG6W

#ifdef CONFIG_SMP
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
mfspr r8,SPRN_PIR; \
Expand Down Expand Up @@ -124,6 +129,8 @@

#define CRITICAL_EXCEPTION_PROLOG \
EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
#define DEBUG_EXCEPTION_PROLOG \
EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1)
#define MCHECK_EXCEPTION_PROLOG \
EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)

Expand Down Expand Up @@ -205,6 +212,60 @@
* save (and later restore) the MSR via SPRN_CSRR1, which will still have
* the MSR_DE bit set.
*/
#ifdef CONFIG_E200
#define DEBUG_EXCEPTION \
START_EXCEPTION(Debug); \
DEBUG_EXCEPTION_PROLOG; \
\
/* \
* If there is a single step or branch-taken exception in an \
* exception entry sequence, it was probably meant to apply to \
* the code where the exception occurred (since exception entry \
* doesn't turn off DE automatically). We simulate the effect \
* of turning off DE on entry to an exception handler by turning \
* off DE in the CSRR1 value and clearing the debug status. \
*/ \
mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
andis. r10,r10,DBSR_IC@h; \
beq+ 2f; \
\
lis r10,KERNELBASE@h; /* check if exception in vectors */ \
ori r10,r10,KERNELBASE@l; \
cmplw r12,r10; \
blt+ 2f; /* addr below exception vectors */ \
\
lis r10,Debug@h; \
ori r10,r10,Debug@l; \
cmplw r12,r10; \
bgt+ 2f; /* addr above exception vectors */ \
\
/* here it looks like we got an inappropriate debug exception. */ \
1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
lis r10,DBSR_IC@h; /* clear the IC event */ \
mtspr SPRN_DBSR,r10; \
/* restore state and get out */ \
lwz r10,_CCR(r11); \
lwz r0,GPR0(r11); \
lwz r1,GPR1(r11); \
mtcrf 0x80,r10; \
mtspr SPRN_DSRR0,r12; \
mtspr SPRN_DSRR1,r9; \
lwz r9,GPR9(r11); \
lwz r12,GPR12(r11); \
mtspr DEBUG_SPRG,r8; \
BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
lwz r10,GPR10-INT_FRAME_SIZE(r8); \
lwz r11,GPR11-INT_FRAME_SIZE(r8); \
mfspr r8,DEBUG_SPRG; \
\
RFDI; \
b .; \
\
/* continue normal handling for a critical exception... */ \
2: mfspr r4,SPRN_DBSR; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
#else
#define DEBUG_EXCEPTION \
START_EXCEPTION(Debug); \
CRITICAL_EXCEPTION_PROLOG; \
Expand Down Expand Up @@ -257,6 +318,7 @@
2: mfspr r4,SPRN_DBSR; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
#endif

#define INSTRUCTION_STORAGE_EXCEPTION \
START_EXCEPTION(InstructionStorage) \
Expand Down
51 changes: 51 additions & 0 deletions arch/ppc/kernel/head_fsl_booke.S
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
#ifndef CONFIG_E200
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
Expand All @@ -118,6 +119,7 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* Fall through, we had to match */
#endif
match_TLB:
mfspr r7,SPRN_MAS0
rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
Expand Down Expand Up @@ -196,8 +198,10 @@ skpinv: addi r6,r6,1 /* Increment */
/* 4. Clear out PIDs & Search info */
li r6,0
mtspr SPRN_PID0,r6
#ifndef CONFIG_E200
mtspr SPRN_PID1,r6
mtspr SPRN_PID2,r6
#endif
mtspr SPRN_MAS6,r6

/* 5. Invalidate mapping we started in */
Expand Down Expand Up @@ -277,14 +281,19 @@ skpinv: addi r6,r6,1 /* Increment */
SET_IVOR(32, SPEUnavailable);
SET_IVOR(33, SPEFloatingPointData);
SET_IVOR(34, SPEFloatingPointRound);
#ifndef CONFIG_E200
SET_IVOR(35, PerformanceMonitor);
#endif

/* Establish the interrupt vector base */
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
mtspr SPRN_IVPR,r4

/* Setup the defaults for TLB entries */
li r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
#ifdef CONFIG_E200
oris r2,r2,MAS4_TLBSELD(1)@h
#endif
mtspr SPRN_MAS4, r2

#if 0
Expand All @@ -293,6 +302,12 @@ skpinv: addi r6,r6,1 /* Increment */
oris r2,r2,HID0_DOZE@h
mtspr SPRN_HID0, r2
#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)
/*
Expand Down Expand Up @@ -414,7 +429,12 @@ interrupt_base:
CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)

/* Machine Check Interrupt */
#ifdef CONFIG_E200
/* no RFMCI, MCSRRs on E200 */
CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
#else
MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
#endif

/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
Expand Down Expand Up @@ -519,8 +539,13 @@ interrupt_base:
/* Floating Point Unavailable Interrupt */
#ifdef CONFIG_PPC_FPU
FP_UNAVAILABLE_EXCEPTION
#else
#ifdef CONFIG_E200
/* E200 treats 'normal' floating point instructions as FP Unavail exception */
EXCEPTION(0x0800, FloatingPointUnavailable, ProgramCheckException, EXC_XFER_EE)
#else
EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
#endif
#endif

/* System Call Interrupt */
Expand Down Expand Up @@ -691,6 +716,7 @@ interrupt_base:
/*
* Local functions
*/

/*
* Data TLB exceptions will bail out to this point
* if they can't resolve the lightweight TLB fault.
Expand Down Expand Up @@ -761,6 +787,31 @@ END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */
mtspr SPRN_MAS3, r11
#endif
#ifdef CONFIG_E200
/* Round robin TLB1 entries assignment */
mfspr r12, SPRN_MAS0

/* Extract TLB1CFG(NENTRY) */
mfspr r11, SPRN_TLB1CFG
andi. r11, r11, 0xfff

/* Extract MAS0(NV) */
andi. r13, r12, 0xfff
addi r13, r13, 1
cmpw 0, r13, r11
addi r12, r12, 1

/* check if we need to wrap */
blt 7f

/* wrap back to first free tlbcam entry */
lis r13, tlbcam_index@ha
lwz r13, tlbcam_index@l(r13)
rlwimi r12, r13, 0, 20, 31
7:
mtspr SPRN_MAS0,r12
#endif /* CONFIG_E200 */

tlbwe

/* Done...restore registers and get out of here. */
Expand Down
8 changes: 8 additions & 0 deletions arch/ppc/kernel/misc.S
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,14 @@ _GLOBAL(flush_instruction_cache)
iccci 0,r3
#endif
#elif CONFIG_FSL_BOOKE
BEGIN_FTR_SECTION
mfspr r3,SPRN_L1CSR0
ori r3,r3,L1CSR0_CFI|L1CSR0_CLFC
/* msync; isync recommended here */
mtspr SPRN_L1CSR0,r3
isync
blr
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
mfspr r3,SPRN_L1CSR1
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
Expand Down
2 changes: 1 addition & 1 deletion arch/ppc/kernel/perfmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
/* A lock to regulate grabbing the interrupt */
DEFINE_SPINLOCK(perfmon_lock);

#ifdef CONFIG_FSL_BOOKE
#if defined (CONFIG_FSL_BOOKE) && !defined (CONFIG_E200)
static void dummy_perf(struct pt_regs *regs)
{
unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
Expand Down
Loading

0 comments on commit 33d9e9b

Please sign in to comment.