diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr.c | 4 | ||||
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr2.c | 4 | ||||
-rw-r--r-- | cpu/ppc4xx/config.mk | 10 | ||||
-rw-r--r-- | cpu/ppc4xx/gpio.c | 42 | ||||
-rw-r--r-- | cpu/ppc4xx/start.S | 331 | ||||
-rw-r--r-- | cpu/ppc4xx/tlb.c | 77 | ||||
-rw-r--r-- | cpu/ppc4xx/traps.c | 107 |
7 files changed, 331 insertions, 244 deletions
diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c index c500d3f..fe7bbab 100644 --- a/cpu/ppc4xx/44x_spd_ddr.c +++ b/cpu/ppc4xx/44x_spd_ddr.c @@ -262,7 +262,7 @@ typedef struct bank_param BANKPARMS; #ifdef CFG_SIMULATE_SPD_EEPROM extern unsigned char cfg_simulate_spd_eeprom[128]; #endif -void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value); +void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value); static unsigned char spd_read(uchar chip, uint addr); static void get_spd_info(unsigned long *dimm_populated, @@ -373,7 +373,7 @@ long int spd_sdram(void) { #ifdef CONFIG_PROG_SDRAM_TLB /* this define should eventually be removed */ /* and program tlb entries for this size (dynamic) */ - program_tlb(0, total_size, MY_TLB_WORD2_I_ENABLE); + program_tlb(0, 0, total_size, MY_TLB_WORD2_I_ENABLE); #endif /* diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 48b9ee2..874cec0 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -144,7 +144,7 @@ typedef enum ddr_cas_id { * Prototypes *-----------------------------------------------------------------------------*/ static unsigned long sdram_memsize(void); -void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value); +void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value); static void get_spd_info(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks); @@ -528,7 +528,7 @@ long int initdram(int board_type) dram_size = sdram_memsize(); /* and program tlb entries for this size (dynamic) */ - program_tlb(0, dram_size, MY_TLB_WORD2_I_ENABLE); + program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE); /*------------------------------------------------------------------ * DQS calibration. diff --git a/cpu/ppc4xx/config.mk b/cpu/ppc4xx/config.mk index 119e061..e7fc3f63 100644 --- a/cpu/ppc4xx/config.mk +++ b/cpu/ppc4xx/config.mk @@ -22,5 +22,13 @@ # PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing +PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -ffixed-r29 -mstring -msoft-float -PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -ffixed-r29 -mstring -Wa,-m405 -mcpu=405 -msoft-float +cfg=$(shell grep configs $(TOPDIR)/include/config.h | sed 's/.*<\(configs.*\)>/\1/') +is440=$(shell grep CONFIG_440 $(TOPDIR)/include/$(cfg)) + +ifneq (,$(findstring CONFIG_440,$(is440))) +PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440 +else +PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405 +endif diff --git a/cpu/ppc4xx/gpio.c b/cpu/ppc4xx/gpio.c index dd84e58..5235203 100644 --- a/cpu/ppc4xx/gpio.c +++ b/cpu/ppc4xx/gpio.c @@ -103,6 +103,18 @@ void gpio_write_bit(int pin, int val) out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) & ~GPIO_VAL(pin)); } +int gpio_read_out_bit(int pin) +{ + u32 offs = 0; + + if (pin >= GPIO_MAX) { + offs = 0x100; + pin -= GPIO_MAX; + } + + return (in32(GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0); +} + #if defined(CFG_440_GPIO_TABLE) void gpio_set_chip_configuration(void) { @@ -157,12 +169,38 @@ void gpio_set_chip_configuration(void) switch (gpio_tab[gpio_core][i].alt_nb) { case GPIO_SEL: if (gpio_core == GPIO0) { - reg = in32(GPIO0_TCR) | (0x80000000 >> (j)); + /* + * Setup output value + * 1 -> high level + * 0 -> low level + * else -> don't touch + */ + reg = in32(GPIO0_OR); + if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) + reg |= (0x80000000 >> (i)); + else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) + reg &= ~(0x80000000 >> (i)); + out32(GPIO0_OR, reg); + + reg = in32(GPIO0_TCR) | (0x80000000 >> (i)); out32(GPIO0_TCR, reg); } if (gpio_core == GPIO1) { - reg = in32(GPIO1_TCR) | (0x80000000 >> (j)); + /* + * Setup output value + * 1 -> high level + * 0 -> low level + * else -> don't touch + */ + reg = in32(GPIO0_OR); + if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) + reg |= (0x80000000 >> (i)); + else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) + reg &= ~(0x80000000 >> (i)); + out32(GPIO0_OR, reg); + + reg = in32(GPIO1_TCR) | (0x80000000 >> (i)); out32(GPIO1_TCR, reg); } diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 78d0042..16df1e7 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -294,11 +294,13 @@ skip_debug_init: mtspr ivor7,r1 /* Floating point unavailable */ li r1,0x0c00 mtspr ivor8,r1 /* System call */ - li r1,0x1000 - mtspr ivor10,r1 /* Decrementer (PIT for 440) */ - li r1,0x1400 - mtspr ivor13,r1 /* Data TLB error */ + li r1,0x0a00 + mtspr ivor9,r1 /* Auxiliary Processor unavailable */ + li r1,0x0900 + mtspr ivor10,r1 /* Decrementer */ li r1,0x1300 + mtspr ivor13,r1 /* Data TLB error */ + li r1,0x1400 mtspr ivor14,r1 /* Instr TLB error */ li r1,0x2000 mtspr ivor15,r1 /* Debug */ @@ -503,11 +505,81 @@ version_string: .ascii " (", __DATE__, " - ", __TIME__, ")" .ascii CONFIG_IDENT_STRING, "\0" -/* - * Maybe this should be moved somewhere else because the current - * location (0x100) is where the CriticalInput Execption should be. - */ . = EXC_OFF_SYS_RESET + .globl _start_of_vectors +_start_of_vectors: + +/* Critical input. */ + CRIT_EXCEPTION(0x100, CritcalInput, UnknownException) + +#ifdef CONFIG_440 +/* Machine check */ + MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException) +#else + CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException) +#endif /* CONFIG_440 */ + +/* Data Storage exception. */ + STD_EXCEPTION(0x300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ + STD_EXCEPTION(0x400, InstStorage, UnknownException) + +/* External Interrupt exception. */ + STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) + +/* Alignment exception. */ + . = 0x600 +Alignment: + EXCEPTION_PROLOG(SRR0, SRR1) + mfspr r4,DAR + stw r4,_DAR(r21) + mfspr r5,DSISR + stw r5,_DSISR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_Alignment: + .long AlignmentException - _start + _START_OFFSET + .long int_return - _start + _START_OFFSET + +/* Program check exception */ + . = 0x700 +ProgramCheck: + EXCEPTION_PROLOG(SRR0, SRR1) + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_ProgramCheck: + .long ProgramCheckException - _start + _START_OFFSET + .long int_return - _start + _START_OFFSET + +#ifdef CONFIG_440 + STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + STD_EXCEPTION(0x900, Decrementer, DecrementerPITException) + STD_EXCEPTION(0xa00, APU, UnknownException) +#endif + STD_EXCEPTION(0xc00, SystemCall, UnknownException) + +#ifdef CONFIG_440 + STD_EXCEPTION(0x1300, DataTLBError, UnknownException) + STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException) +#else + STD_EXCEPTION(0x1000, PIT, DecrementerPITException) + STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) + STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) +#endif + CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException ) + + .globl _end_of_vectors +_end_of_vectors: + . = _START_OFFSET #endif .globl _start _start: @@ -817,7 +889,7 @@ _start: */ lis r3,CFG_OCM_DATA_ADDR@h /* OCM location */ ori r3,r3,CFG_OCM_DATA_ADDR@l - ori r3,r3,0x8270 /* 32K Offset, 16K for Bank 1, R/W/Enable */ + ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */ mtdcr ocmplb3cr1,r3 /* Set PLB Access */ ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */ mtdcr ocmplb3cr2,r3 /* Set PLB Access */ @@ -1017,107 +1089,6 @@ start_ram: #ifndef CONFIG_NAND_SPL -/*****************************************************************************/ - .globl _start_of_vectors -_start_of_vectors: - -#if 0 -/*TODO Fixup _start above so we can do this*/ -/* Critical input. */ - CRIT_EXCEPTION(0x100, CritcalInput, CritcalInputException) -#endif - -/* Machine check */ - CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException) - -/* Data Storage exception. */ - STD_EXCEPTION(0x300, DataStorage, UnknownException) - -/* Instruction Storage exception. */ - STD_EXCEPTION(0x400, InstStorage, UnknownException) - -/* External Interrupt exception. */ - STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) - -/* Alignment exception. */ - . = 0x600 -Alignment: - EXCEPTION_PROLOG - mfspr r4,DAR - stw r4,_DAR(r21) - mfspr r5,DSISR - stw r5,_DSISR(r21) - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - lwz r6,GOT(transfer_to_handler) - mtlr r6 - blrl -.L_Alignment: - .long AlignmentException - _start + EXC_OFF_SYS_RESET - .long int_return - _start + EXC_OFF_SYS_RESET - -/* Program check exception */ - . = 0x700 -ProgramCheck: - EXCEPTION_PROLOG - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - lwz r6,GOT(transfer_to_handler) - mtlr r6 - blrl -.L_ProgramCheck: - .long ProgramCheckException - _start + EXC_OFF_SYS_RESET - .long int_return - _start + EXC_OFF_SYS_RESET - - /* No FPU on MPC8xx. This exception is not supposed to happen. - */ - STD_EXCEPTION(0x800, FPUnavailable, UnknownException) - - /* I guess we could implement decrementer, and may have - * to someday for timekeeping. - */ - STD_EXCEPTION(0x900, Decrementer, timer_interrupt) - STD_EXCEPTION(0xa00, Trap_0a, UnknownException) - STD_EXCEPTION(0xb00, Trap_0b, UnknownException) - STD_EXCEPTION(0xc00, SystemCall, UnknownException) - STD_EXCEPTION(0xd00, SingleStep, UnknownException) - - STD_EXCEPTION(0xe00, Trap_0e, UnknownException) - STD_EXCEPTION(0xf00, Trap_0f, UnknownException) - - /* On the MPC8xx, this is a software emulation interrupt. It occurs - * for all unimplemented and illegal instructions. - */ - STD_EXCEPTION(0x1000, PIT, PITException) - - STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) - STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) - STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException) - STD_EXCEPTION(0x1400, DataTLBError, UnknownException) - - STD_EXCEPTION(0x1500, Reserved5, UnknownException) - STD_EXCEPTION(0x1600, Reserved6, UnknownException) - STD_EXCEPTION(0x1700, Reserved7, UnknownException) - STD_EXCEPTION(0x1800, Reserved8, UnknownException) - STD_EXCEPTION(0x1900, Reserved9, UnknownException) - STD_EXCEPTION(0x1a00, ReservedA, UnknownException) - STD_EXCEPTION(0x1b00, ReservedB, UnknownException) - - STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException) - STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException) - STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException) - STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException) - - CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException ) - - .globl _end_of_vectors -_end_of_vectors: - - - . = 0x2100 - /* * This code finishes saving the registers to the exception frame * and jumps to the appropriate handler for the exception. @@ -1133,28 +1104,12 @@ transfer_to_handler: SAVE_4GPRS(8, r21) SAVE_8GPRS(12, r21) SAVE_8GPRS(24, r21) -#if 0 - andi. r23,r23,MSR_PR - mfspr r23,SPRG3 /* if from user, fix up tss.regs */ - beq 2f - addi r24,r1,STACK_FRAME_OVERHEAD - stw r24,PT_REGS(r23) -2: addi r2,r23,-TSS /* set r2 to current */ - tovirt(r2,r2,r23) -#endif mflr r23 andi. r24,r23,0x3f00 /* get vector offset */ stw r24,TRAP(r21) li r22,0 stw r22,RESULT(r21) mtspr SPRG2,r22 /* r1 is now kernel sp */ -#if 0 - addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */ - cmplw 0,r1,r2 - cmplw 1,r1,r24 - crand 1,1,4 - bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */ -#endif lwz r24,0(r23) /* virtual address of handler */ lwz r23,4(r23) /* where to go when done */ mtspr SRR0,r24 @@ -1215,16 +1170,64 @@ crit_return: REST_GPR(31, r1) lwz r2,_NIP(r1) /* Restore environment */ lwz r0,_MSR(r1) - mtspr 990,r2 /* SRR2 */ - mtspr 991,r0 /* SRR3 */ + mtspr csrr0,r2 + mtspr csrr1,r0 lwz r0,GPR0(r1) lwz r2,GPR2(r1) lwz r1,GPR1(r1) SYNC rfci -/* Cache functions. -*/ +#ifdef CONFIG_440 +mck_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr mcsrr0,r2 + mtspr mcsrr1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfmci +#endif /* CONFIG_440 */ + + +/* + * Cache functions. + * + * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, + * although for some cache-ralated calls stubs have to be provided to satisfy + * symbols resolution. + * + */ +#ifdef CONFIG_440 + .globl dcache_disable +dcache_disable: + blr + + .globl dcache_status +dcache_status: + blr +#else flush_dcache: addis r9,r0,0x0002 /* set mask for EE and CE msr bits */ ori r9,r9,0x8000 @@ -1303,24 +1306,13 @@ dcache_status: mfdccr r3 srwi r3, r3, 31 /* >>31 => select bit 0 */ blr +#endif .globl get_pvr get_pvr: mfspr r3, PVR blr -#if !defined(CONFIG_440) - .globl wr_pit -wr_pit: - mtspr pit, r3 - blr -#endif - - .globl wr_tcr -wr_tcr: - mtspr tcr, r3 - blr - /*------------------------------------------------------------------------------- */ /* Function: out16 */ /* Description: Output 16 bits */ @@ -1518,7 +1510,7 @@ relocate_code: * initialization, now running from RAM. */ - addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET + addi r0, r10, in_ram - _start + _START_OFFSET mtlr r0 blr /* NEVER RETURNS! */ @@ -1588,7 +1580,7 @@ clear_bss: */ .globl trap_init trap_init: - lwz r7, GOT(_start) + lwz r7, GOT(_start_of_vectors) lwz r8, GOT(_end_of_vectors) li r9, 0x100 /* reset vector always at 0x100 */ @@ -1608,35 +1600,48 @@ trap_init: /* * relocate `hdlr' and `int_return' entries */ - li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET - li r8, Alignment - _start + EXC_OFF_SYS_RESET + li r7, .L_MachineCheck - _start + _START_OFFSET + li r8, Alignment - _start + _START_OFFSET 2: bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ + addi r7, r7, 0x100 /* next exception vector */ cmplw 0, r7, r8 blt 2b - li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET + li r7, .L_Alignment - _start + _START_OFFSET bl trap_reloc - li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET + li r7, .L_ProgramCheck - _start + _START_OFFSET bl trap_reloc - li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET - li r8, SystemCall - _start + EXC_OFF_SYS_RESET -3: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 3b +#ifdef CONFIG_440 + li r7, .L_FPUnavailable - _start + _START_OFFSET + bl trap_reloc - li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET - li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET -4: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 4b + li r7, .L_Decrementer - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_APU - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_InstructionTLBError - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_DataTLBError - _start + _START_OFFSET + bl trap_reloc +#else /* CONFIG_440 */ + li r7, .L_PIT - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_InstructionTLBMiss - _start + _START_OFFSET + bl trap_reloc + + li r7, .L_DataTLBMiss - _start + _START_OFFSET + bl trap_reloc +#endif /* CONFIG_440 */ + + li r7, .L_DebugBreakpoint - _start + _START_OFFSET + bl trap_reloc #if !defined(CONFIG_440) addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ diff --git a/cpu/ppc4xx/tlb.c b/cpu/ppc4xx/tlb.c index 50344a4..6c916ef 100644 --- a/cpu/ppc4xx/tlb.c +++ b/cpu/ppc4xx/tlb.c @@ -36,7 +36,8 @@ typedef struct region { unsigned long tlb_word2_i_value; } region_t; -static int add_tlb_entry(unsigned long base_addr, +static int add_tlb_entry(unsigned long phys_addr, + unsigned long virt_addr, unsigned long tlb_word0_size_value, unsigned long tlb_word2_i_value) { @@ -55,9 +56,9 @@ static int add_tlb_entry(unsigned long base_addr, return -1; /* Second, create the TLB entry */ - tlb_word0_value = TLB_WORD0_EPN_ENCODE(base_addr) | TLB_WORD0_V_ENABLE | + tlb_word0_value = TLB_WORD0_EPN_ENCODE(virt_addr) | TLB_WORD0_V_ENABLE | TLB_WORD0_TS_0 | tlb_word0_size_value; - tlb_word1_value = TLB_WORD1_RPN_ENCODE(base_addr) | TLB_WORD1_ERPN_ENCODE(0); + tlb_word1_value = TLB_WORD1_RPN_ENCODE(phys_addr) | TLB_WORD1_ERPN_ENCODE(0); tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE | TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE | TLB_WORD2_W_DISABLE | tlb_word2_i_value | @@ -81,7 +82,9 @@ static int add_tlb_entry(unsigned long base_addr, return 0; } -static void program_tlb_addr(unsigned long base_addr, unsigned long mem_size, +static void program_tlb_addr(unsigned long phys_addr, + unsigned long virt_addr, + unsigned long mem_size, unsigned long tlb_word2_i_value) { int rc; @@ -91,70 +94,78 @@ static void program_tlb_addr(unsigned long base_addr, unsigned long mem_size, while (mem_size != 0) { rc = 0; /* Add the TLB entries in to map the region. */ - if (((base_addr & TLB_256MB_ALIGN_MASK) == base_addr) && + if (((phys_addr & TLB_256MB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_256MB_SIZE)) { /* Add a 256MB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_256MB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_256MB, tlb_i)) == 0) { mem_size -= TLB_256MB_SIZE; - base_addr += TLB_256MB_SIZE; + phys_addr += TLB_256MB_SIZE; } - } else if (((base_addr & TLB_16MB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_16MB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_16MB_SIZE)) { /* Add a 16MB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_16MB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_16MB, tlb_i)) == 0) { mem_size -= TLB_16MB_SIZE; - base_addr += TLB_16MB_SIZE; + phys_addr += TLB_16MB_SIZE; } - } else if (((base_addr & TLB_1MB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_1MB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_1MB_SIZE)) { /* Add a 1MB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_1MB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_1MB, tlb_i)) == 0) { mem_size -= TLB_1MB_SIZE; - base_addr += TLB_1MB_SIZE; + phys_addr += TLB_1MB_SIZE; } - } else if (((base_addr & TLB_256KB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_256KB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_256KB_SIZE)) { /* Add a 256KB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_256KB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_256KB, tlb_i)) == 0) { mem_size -= TLB_256KB_SIZE; - base_addr += TLB_256KB_SIZE; + phys_addr += TLB_256KB_SIZE; } - } else if (((base_addr & TLB_64KB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_64KB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_64KB_SIZE)) { /* Add a 64KB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_64KB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_64KB, tlb_i)) == 0) { mem_size -= TLB_64KB_SIZE; - base_addr += TLB_64KB_SIZE; + phys_addr += TLB_64KB_SIZE; } - } else if (((base_addr & TLB_16KB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_16KB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_16KB_SIZE)) { /* Add a 16KB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_16KB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_16KB, tlb_i)) == 0) { mem_size -= TLB_16KB_SIZE; - base_addr += TLB_16KB_SIZE; + phys_addr += TLB_16KB_SIZE; } - } else if (((base_addr & TLB_4KB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_4KB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_4KB_SIZE)) { /* Add a 4KB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_4KB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_4KB, tlb_i)) == 0) { mem_size -= TLB_4KB_SIZE; - base_addr += TLB_4KB_SIZE; + phys_addr += TLB_4KB_SIZE; } - } else if (((base_addr & TLB_1KB_ALIGN_MASK) == base_addr) && + } else if (((phys_addr & TLB_1KB_ALIGN_MASK) == phys_addr) && (mem_size >= TLB_1KB_SIZE)) { /* Add a 1KB TLB entry */ - if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_1KB, tlb_i)) == 0) { + if ((rc = add_tlb_entry(phys_addr, virt_addr, + TLB_WORD0_SIZE_1KB, tlb_i)) == 0) { mem_size -= TLB_1KB_SIZE; - base_addr += TLB_1KB_SIZE; + phys_addr += TLB_1KB_SIZE; } } else { printf("ERROR: no TLB size exists for the base address 0x%0X.\n", - base_addr); + phys_addr); } if (rc != 0) printf("ERROR: no TLB entries available for the base addr 0x%0X.\n", - base_addr); + phys_addr); } return; @@ -166,16 +177,16 @@ static void program_tlb_addr(unsigned long base_addr, unsigned long mem_size, * Common usage for boards with SDRAM DIMM modules to dynamically * configure the TLB's for the SDRAM */ -void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value) +void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value) { region_t region_array; - region_array.base = start; + region_array.base = phys_addr; region_array.size = size; region_array.tlb_word2_i_value = tlb_word2_i_value; /* en-/disable cache */ /* Call the routine to add in the tlb entries for the memory regions */ - program_tlb_addr(region_array.base, region_array.size, + program_tlb_addr(region_array.base, virt_addr, region_array.size, region_array.tlb_word2_i_value); return; diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c index 6aecca2..54659d3 100644 --- a/cpu/ppc4xx/traps.c +++ b/cpu/ppc4xx/traps.c @@ -36,6 +36,8 @@ #include <command.h> #include <asm/processor.h> +DECLARE_GLOBAL_DATA_PTR; + #if (CONFIG_COMMANDS & CFG_CMD_KGDB) int (*debugger_exception_handler)(struct pt_regs *) = 0; #endif @@ -45,8 +47,7 @@ extern unsigned long search_exception_table(unsigned long); /* THIS NEEDS CHANGING to use the board info structure. */ -#define END_OF_MEM 0x00400000 - +#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize) static __inline__ void set_tsr(unsigned long val) { @@ -88,29 +89,29 @@ extern void do_bedbug_breakpoint(struct pt_regs *); void print_backtrace(unsigned long *sp) { - int cnt = 0; - unsigned long i; - - printf("Call backtrace: "); - while (sp) { - if ((uint)sp > END_OF_MEM) - break; - - i = sp[1]; - if (cnt++ % 7 == 0) - printf("\n"); - printf("%08lX ", i); - if (cnt > 32) break; - sp = (unsigned long *)*sp; - } - printf("\n"); + int cnt = 0; + unsigned long i; + + printf("Call backtrace: "); + while (sp) { + if ((uint)sp > END_OF_MEM) + break; + + i = sp[1]; + if (cnt++ % 7 == 0) + printf("\n"); + printf("%08lX ", i); + if (cnt > 32) break; + sp = (unsigned long *)*sp; + } + printf("\n"); } void show_regs(struct pt_regs * regs) { int i; - printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", + printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n", regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, @@ -139,14 +140,14 @@ _exception(int signr, struct pt_regs *regs) { show_regs(regs); print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception in kernel pc %lx signal %d",regs->nip,signr); + panic("Exception"); } void MachineCheckException(struct pt_regs *regs) { - unsigned long fixup; - + unsigned long fixup, val; + /* Probing PCI using config cycles cause this exception * when a device is not present. Catch it and return to * the PCI exception handler. @@ -161,26 +162,50 @@ MachineCheckException(struct pt_regs *regs) return; #endif - printf("Machine check in kernel mode.\n"); + printf("Machine Check Exception.\n"); printf("Caused by (from msr): "); - printf("regs %p ",regs); - switch( regs->msr & 0x000F0000) { - case (0x80000000>>12): - printf("Machine check signal - probably due to mm fault\n" - "with mmu off\n"); - break; - case (0x80000000>>13): - printf("Transfer error ack signal\n"); - break; - case (0x80000000>>14): - printf("Data parity signal\n"); - break; - case (0x80000000>>15): - printf("Address parity signal\n"); - break; - default: - printf("Unknown values in msr\n"); + printf("regs %p ", regs); + + val = get_esr(); + +#if !defined(CONFIG_440) + if (val& ESR_IMCP) { + printf("Instruction"); + mtspr(ESR, val & ~ESR_IMCP); + } else + printf("Data"); + printf(" machine check.\n"); + +#elif defined(CONFIG_440) + if (val& ESR_IMCP){ + printf("Instruction Synchronous Machine Check exception\n"); + mtspr(SPRN_ESR, val & ~ESR_IMCP); } + else { + val = mfspr(MCSR); + if (val & MCSR_IB) + printf("Instruction Read PLB Error\n"); + if (val & MCSR_DRB) + printf("Data Read PLB Error\n"); + if (val & MCSR_DWB) + printf("Data Write PLB Error\n"); + if (val & MCSR_TLBP) + printf("TLB Parity Error\n"); + if (val & MCSR_ICP){ + /*flush_instruction_cache(); */ + printf("I-Cache Parity Error\n"); + } + if (val & MCSR_DCSP) + printf("D-Cache Search Parity Error\n"); + if (val & MCSR_DCFP) + printf("D-Cache Flush Parity Error\n"); + if (val & MCSR_IMPE) + printf("Machine Check exception is imprecise\n"); + + /* Clear MCSR */ + mtspr(SPRN_MCSR, val); + } +#endif show_regs(regs); print_backtrace((unsigned long *)regs->gpr[1]); panic("machine check"); @@ -224,7 +249,7 @@ ProgramCheckException(struct pt_regs *regs) } void -PITException(struct pt_regs *regs) +DecrementerPITException(struct pt_regs *regs) { /* * Reset PIT interrupt |