diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.c | 47 | ||||
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.h | 19 | ||||
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr.c | 2 | ||||
-rw-r--r-- | cpu/ppc4xx/serial.c | 9 | ||||
-rw-r--r-- | cpu/ppc4xx/speed.c | 33 | ||||
-rwxr-xr-x | cpu/ppc4xx/traps.c | 49 |
6 files changed, 114 insertions, 45 deletions
diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c index d6c4be5..bf68cc1 100644 --- a/cpu/ppc4xx/440spe_pcie.c +++ b/cpu/ppc4xx/440spe_pcie.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2006 + * (C) Copyright 2006 - 2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * Copyright (c) 2005 Cisco Systems. All rights reserved. @@ -40,6 +40,34 @@ enum { LNKW_X8 = 0x8 }; +static inline int pcie_in_8(const volatile unsigned char __iomem *addr) +{ + int ret; + + PCIE_IN(lbzx, ret, addr); + + return ret; +} + +static inline int pcie_in_le16(const volatile unsigned short __iomem *addr) +{ + int ret; + + PCIE_IN(lhbrx, ret, addr) + + return ret; +} + +static inline unsigned pcie_in_le32(const volatile unsigned __iomem *addr) +{ + unsigned ret; + + PCIE_IN(lwbrx, ret, addr); + + return ret; +} + + static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, int offset, int len, u32 *val) { @@ -55,13 +83,13 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, switch (len) { case 1: - *val = in_8(hose->cfg_data + offset); + *val = pcie_in_8(hose->cfg_data + offset); break; case 2: - *val = in_le16((u16 *)(hose->cfg_data + offset)); + *val = pcie_in_le16((u16 *)(hose->cfg_data + offset)); break; default: - *val = in_le32((u32 *)(hose->cfg_data + offset)); + *val = pcie_in_le32((u32*)(hose->cfg_data + offset)); break; } return 0; @@ -783,9 +811,14 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) /* * Set bus numbers on our root port */ - out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); - out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); - out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); + if (ppc440spe_revB()) { + out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); + out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); + out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); + } else { + out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); + out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0); + } /* * Set up outbound translation to hose->mem_space from PLB diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h index 2becc77..eb7cecf 100644 --- a/cpu/ppc4xx/440spe_pcie.h +++ b/cpu/ppc4xx/440spe_pcie.h @@ -145,8 +145,8 @@ #define PECFG_PIMEN 0x33c #define PECFG_PIM0LAL 0x340 #define PECFG_PIM0LAH 0x344 -#define PECFG_PIM1LAL 0x348 -#define PECFG_PIM1LAH 0x34c +#define PECFG_PIM1LAL 0x348 +#define PECFG_PIM1LAH 0x34c #define PECFG_PIM01SAL 0x350 #define PECFG_PIM01SAH 0x354 @@ -161,6 +161,21 @@ mtdcr(DCRN_SDR0_CFGADDR, offset); \ mtdcr(DCRN_SDR0_CFGDATA,data);}) +#define PCIE_IN(opcode, ret, addr) \ + __asm__ __volatile__( \ + "sync\n" \ + #opcode " %0,0,%1\n" \ + "1: twi 0,%0,0\n" \ + "isync\n" \ + "b 3f\n" \ + "2: li %0,-1\n" \ + "3:\n" \ + ".section __ex_table,\"a\"\n" \ + ".balign 4\n" \ + ".long 1b,2b\n" \ + ".previous\n" \ + : "=r" (ret) : "r" (addr), "m" (*addr)); + int ppc440spe_init_pcie(void); int ppc440spe_init_pcie_rootport(int port); void yucca_setup_pcie_fpga_rootpoint(int port); diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c index e5f296e..4a4c6f2 100644 --- a/cpu/ppc4xx/44x_spd_ddr.c +++ b/cpu/ppc4xx/44x_spd_ddr.c @@ -269,7 +269,7 @@ struct bank_param { typedef struct bank_param BANKPARMS; #ifdef CFG_SIMULATE_SPD_EEPROM -extern unsigned char cfg_simulate_spd_eeprom[128]; +extern const unsigned char cfg_simulate_spd_eeprom[128]; #endif static unsigned char spd_read(uchar chip, uint addr); diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c index e62dd9d..a75e5ee 100644 --- a/cpu/ppc4xx/serial.c +++ b/cpu/ppc4xx/serial.c @@ -448,12 +448,17 @@ static void serial_divs (int baudrate, unsigned long *pudiv, unsigned long i; unsigned long est; /* current estimate */ unsigned long plloutb; + unsigned long cpr_pllc; u32 reg; + /* check the pll feedback source */ + mfcpr(cprpllc, cpr_pllc); + get_sys_info(&sysinfo); - plloutb = ((CONFIG_SYS_CLK_FREQ * sysinfo.pllFwdDiv * sysinfo.pllFbkDiv) - / sysinfo.pllFwdDivB); + plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ? + sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * sysinfo.pllFbkDiv) / + sysinfo.pllFwdDivB); udiv = 256; /* Assume lowest possible serial clk */ div = plloutb / (16 * baudrate); /* total divisor */ umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */ diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index 028b11a..da5330a 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -771,6 +771,7 @@ ulong get_PCI_freq (void) void get_sys_info (PPC405_SYS_INFO * sysInfo) { unsigned long cpr_plld; + unsigned long cpr_pllc; unsigned long cpr_primad; unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000); unsigned long primad_cpudv; @@ -780,6 +781,7 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Read PLL Mode registers */ mfcpr(cprplld, cpr_plld); + mfcpr(cprpllc, cpr_pllc); /* * Determine forward divider A @@ -787,20 +789,18 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16); /* - * Determine forward divider B (should be equal to A) + * Determine forward divider B */ sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8); - if (sysInfo->pllFwdDivB == 0) { + if (sysInfo->pllFwdDivB == 0) sysInfo->pllFwdDivB = 8; - } /* * Determine FBK_DIV. */ sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24); - if (sysInfo->pllFbkDiv == 0) { + if (sysInfo->pllFbkDiv == 0) sysInfo->pllFbkDiv = 256; - } /* * Read CPR_PRIMAD register @@ -810,30 +810,30 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Determine PLB_DIV. */ sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16); - if (sysInfo->pllPlbDiv == 0) { + if (sysInfo->pllPlbDiv == 0) sysInfo->pllPlbDiv = 16; - } /* * Determine EXTBUS_DIV. */ sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK); - if (sysInfo->pllExtBusDiv == 0) { + if (sysInfo->pllExtBusDiv == 0) sysInfo->pllExtBusDiv = 16; - } /* * Determine OPB_DIV. */ sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8); - if (sysInfo->pllOpbDiv == 0) { + if (sysInfo->pllOpbDiv == 0) sysInfo->pllOpbDiv = 16; - } /* * Determine the M factor */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB; + if (cpr_pllc & PLLC_SRC_MASK) + m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB; + else + m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv; /* * Determine VCO clock frequency @@ -845,16 +845,17 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Determine CPU clock frequency */ primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24); - if (primad_cpudv == 0) { + if (primad_cpudv == 0) primad_cpudv = 16; - } - sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / primad_cpudv; + sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) / + sysInfo->pllFwdDiv / primad_cpudv; /* * Determine PLB clock frequency */ - sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / sysInfo->pllPlbDiv; + sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) / + sysInfo->pllFwdDiv / sysInfo->pllPlbDiv; } /******************************************** diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c index eb9420e..de5fde9 100755 --- a/cpu/ppc4xx/traps.c +++ b/cpu/ppc4xx/traps.c @@ -147,14 +147,21 @@ MachineCheckException(struct pt_regs *regs) unsigned long fixup, val; #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) u32 value2; + int corr_ecc = 0; + int uncorr_ecc = 0; #endif - /* Probing PCI using config cycles cause this exception - * when a device is not present. Catch it and return to - * the PCI exception handler. + /* Probing PCI(E) using config cycles may cause this exception + * when a device is not present. To gracefully recover in such + * scenarios config read/write routines need to be instrumented in + * order to return via fixup handler. For examples refer to + * pcie_in_8(), pcie_in_le16() and pcie_in_le32() */ if ((fixup = search_exception_table(regs->nip)) != 0) { regs->nip = fixup; + val = mfspr(MCSR); + /* Clear MCSR */ + mtspr(SPRN_MCSR, val); return; } @@ -214,14 +221,22 @@ MachineCheckException(struct pt_regs *regs) printf("DDR0: At least one interrupt active\n"); if (val & 0x40) printf("DDR0: DRAM initialization complete.\n"); - if (val & 0x20) + if (val & 0x20) { printf("DDR0: Multiple uncorrectable ECC events.\n"); - if (val & 0x10) + uncorr_ecc = 1; + } + if (val & 0x10) { printf("DDR0: Single uncorrectable ECC event.\n"); - if (val & 0x08) + uncorr_ecc = 1; + } + if (val & 0x08) { printf("DDR0: Multiple correctable ECC events.\n"); - if (val & 0x04) + corr_ecc = 1; + } + if (val & 0x04) { printf("DDR0: Single correctable ECC event.\n"); + corr_ecc = 1; + } if (val & 0x02) printf("Multiple accesses outside the defined" " physical memory space detected\n"); @@ -252,11 +267,11 @@ MachineCheckException(struct pt_regs *regs) printf("DDR0: No DDR0 error know 0x%x %p\n", val, value2); } mfsdram(DDR0_23, val); - if ( (val >> 16) & 0xff) + if (((val >> 16) & 0xff) && corr_ecc) printf("DDR0: Syndrome for correctable ECC event 0x%x\n", (val >> 16) & 0xff); mfsdram(DDR0_23, val); - if ( (val >> 8) & 0xff) + if (((val >> 8) & 0xff) && uncorr_ecc) printf("DDR0: Syndrome for uncorrectable ECC event 0x%x\n", (val >> 8) & 0xff); mfsdram(DDR0_33, val); @@ -264,28 +279,28 @@ MachineCheckException(struct pt_regs *regs) printf("DDR0: Address of command that caused an " "Out-of-Range interrupt %p\n", val); mfsdram(DDR0_34, val); - if (val) + if (val && uncorr_ecc) printf("DDR0: Address of uncorrectable ECC event %p\n", val); mfsdram(DDR0_35, val); - if (val) + if (val && uncorr_ecc) printf("DDR0: Address of uncorrectable ECC event %p\n", val); mfsdram(DDR0_36, val); - if (val) + if (val && uncorr_ecc) printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val); mfsdram(DDR0_37, val); - if (val) + if (val && uncorr_ecc) printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val); mfsdram(DDR0_38, val); - if (val) + if (val && corr_ecc) printf("DDR0: Address of correctable ECC event %p\n", val); mfsdram(DDR0_39, val); - if (val) + if (val && corr_ecc) printf("DDR0: Address of correctable ECC event %p\n", val); mfsdram(DDR0_40, val); - if (val) + if (val && corr_ecc) printf("DDR0: Data of correctable ECC event 0x%08x\n", val); mfsdram(DDR0_41, val); - if (val) + if (val && corr_ecc) printf("DDR0: Data of correctable ECC event 0x%08x\n", val); #endif /* CONFIG_440EPX */ #endif /* CONFIG_440 */ |