summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu/ppc4xx/440spe_pcie.c59
-rw-r--r--cpu/ppc4xx/440spe_pcie.h16
-rw-r--r--cpu/ppc4xx/traps.c6
3 files changed, 37 insertions, 44 deletions
diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c
index bf68cc1..2d0b406 100644
--- a/cpu/ppc4xx/440spe_pcie.c
+++ b/cpu/ppc4xx/440spe_pcie.c
@@ -40,31 +40,24 @@ enum {
LNKW_X8 = 0x8
};
-static inline int pcie_in_8(const volatile unsigned char __iomem *addr)
+static void pcie_dmer_disable(void)
{
- 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;
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA);
}
-static inline unsigned pcie_in_le32(const volatile unsigned __iomem *addr)
+static void pcie_dmer_enable(void)
{
- unsigned ret;
-
- PCIE_IN(lwbrx, ret, addr);
-
- return ret;
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA);
}
@@ -81,17 +74,27 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
devfn = PCI_BDF(0,0,0);
offset += devfn << 4;
+ /*
+ * Reading from configuration space of non-existing device can
+ * generate transaction errors. For the read duration we suppress
+ * assertion of machine check exceptions to avoid those.
+ */
+ pcie_dmer_disable ();
+
switch (len) {
case 1:
- *val = pcie_in_8(hose->cfg_data + offset);
+ *val = in_8(hose->cfg_data + offset);
break;
case 2:
- *val = pcie_in_le16((u16 *)(hose->cfg_data + offset));
+ *val = in_le16((u16 *)(hose->cfg_data + offset));
break;
default:
- *val = pcie_in_le32((u32*)(hose->cfg_data + offset));
+ *val = in_le32((u32*)(hose->cfg_data + offset));
break;
}
+
+ pcie_dmer_enable ();
+
return 0;
}
@@ -107,6 +110,11 @@ static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
devfn = PCI_BDF(0,0,0);
offset += devfn << 4;
+ /*
+ * Suppress MCK exceptions, similar to pcie_read_config()
+ */
+ pcie_dmer_disable ();
+
switch (len) {
case 1:
out_8(hose->cfg_data + offset, val);
@@ -118,6 +126,9 @@ static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
out_le32((u32 *)(hose->cfg_data + offset), val);
break;
}
+
+ pcie_dmer_enable ();
+
return 0;
}
diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h
index eb7cecf..38745eb 100644
--- a/cpu/ppc4xx/440spe_pcie.h
+++ b/cpu/ppc4xx/440spe_pcie.h
@@ -38,6 +38,7 @@
#define DCRN_PEGPL_REGBAL(base) (base + 0x13)
#define DCRN_PEGPL_REGMSK(base) (base + 0x14)
#define DCRN_PEGPL_SPECIAL(base) (base + 0x15)
+#define DCRN_PEGPL_CFG(base) (base + 0x16)
/*
* System DCRs (SDRs)
@@ -161,20 +162,7 @@
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));
+#define GPL_DMER_MASK_DISA 0x02000000
int ppc440spe_init_pcie(void);
int ppc440spe_init_pcie_rootport(int port);
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c
index f5365cb..38b6f89 100644
--- a/cpu/ppc4xx/traps.c
+++ b/cpu/ppc4xx/traps.c
@@ -151,12 +151,6 @@ MachineCheckException(struct pt_regs *regs)
int uncorr_ecc = 0;
#endif
- /* 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);