summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ppc4xx/440spe_pcie.c47
-rw-r--r--cpu/ppc4xx/440spe_pcie.h19
-rw-r--r--cpu/ppc4xx/44x_spd_ddr.c2
-rw-r--r--cpu/ppc4xx/serial.c9
-rw-r--r--cpu/ppc4xx/speed.c33
-rwxr-xr-xcpu/ppc4xx/traps.c49
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 */