pcie-designware: make PCIe RC work on QSR1000
Change-Id: I8eb888de3bde63a2794f5c68f9422e5719adcb29
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index aafd766..7cd1bf9 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -79,6 +79,28 @@
int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
{
+#ifdef CONFIG_ARCH_QSR1000
+ u32 reg_val;
+ void *walker = ®_val;
+ u32 where = (u32) addr;
+
+ walker += (where & 0x3);
+ addr = (void __iomem *) (where & ~0x3);
+ reg_val = readl(addr);
+
+ if (size == 1)
+ *val = *(u8 __force *) walker;
+ else if (size == 2)
+ *val = *(u16 __force *) walker;
+ else if (size == 4)
+ *val = reg_val;
+ else {
+ *val = 0;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+#else
if ((uintptr_t)addr & (size - 1)) {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
@@ -96,10 +118,34 @@
}
return PCIBIOS_SUCCESSFUL;
+#endif
}
int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val)
{
+#ifdef CONFIG_ARCH_QSR1000
+ u32 reg_val;
+ void *walker = ®_val;
+ u32 where = (u32) addr;
+
+ walker += (where & 0x3);
+ addr = (void __iomem *) (where & ~0x3);
+
+ if (size == 4)
+ writel(val, addr);
+ else if (size == 2) {
+ reg_val = readl(addr);
+ *(u16 __force *) walker = val;
+ writel(reg_val, addr);
+ } else if (size == 1) {
+ reg_val = readl(addr);
+ *(u8 __force *) walker = val;
+ writel(reg_val, addr);
+ } else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+#else
if ((uintptr_t)addr & (size - 1))
return PCIBIOS_BAD_REGISTER_NUMBER;
@@ -113,6 +159,7 @@
return PCIBIOS_BAD_REGISTER_NUMBER;
return PCIBIOS_SUCCESSFUL;
+#endif
}
static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val)
@@ -599,13 +646,17 @@
va_cfg_base = pp->va_cfg1_base;
}
+#ifndef CONFIG_ARCH_QSR1000
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
+#endif
ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
+#ifndef CONFIG_ARCH_QSR1000
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
+#endif
return ret;
}
@@ -636,13 +687,17 @@
va_cfg_base = pp->va_cfg1_base;
}
+#ifndef CONFIG_ARCH_QSR1000
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
type, cpu_addr,
busdev, cfg_size);
+#endif
ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
+#ifndef CONFIG_ARCH_QSR1000
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_IO, pp->io_base,
pp->io_bus_addr, pp->io_size);
+#endif
return ret;
}
@@ -778,10 +833,12 @@
* uses its own address translation component rather than ATU, so
* we should not program the ATU here.
*/
+#ifndef CONFIG_ARCH_QSR1000
if (!pp->ops->rd_other_conf)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
PCIE_ATU_TYPE_MEM, pp->mem_base,
pp->mem_bus_addr, pp->mem_size);
+#endif
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);