aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Crispin <john@openwrt.org>2014-09-12 06:53:09 +0000
committerJohn Crispin <john@openwrt.org>2014-09-12 06:53:09 +0000
commit78c914ffe52e84b05c6d6ad33d9232fb980f1725 (patch)
tree4da13d32f9f34042252f44a71ae1a86ed48640be
parentdbdd8906ac776e9b8d51284d4dc0ce24920a2231 (diff)
downloadupstream-78c914ffe52e84b05c6d6ad33d9232fb980f1725.tar.gz
upstream-78c914ffe52e84b05c6d6ad33d9232fb980f1725.tar.bz2
upstream-78c914ffe52e84b05c6d6ad33d9232fb980f1725.zip
atheros: ar2315-pci: rework the configuration access code
Use __raw_{read,write}l accessors and use Abort interrupt to detect a configuration space read/write errors. The second change improves errors detection, what improves the device presence detection and helps us to avoid following (and similar) errors: pci 0000:00:00.2: ignoring class 0x7e0200 (doesn't match header type 02) pci 0000:00:00.2: bridge configuration invalid ([bus 03-90]), reconfiguring pci 0000:00:00.2: not setting up bridge for bus 0000:01 Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com> SVN-Revision: 42502
-rw-r--r--target/linux/atheros/patches-3.14/105-ar2315_pci.patch82
1 files changed, 48 insertions, 34 deletions
diff --git a/target/linux/atheros/patches-3.14/105-ar2315_pci.patch b/target/linux/atheros/patches-3.14/105-ar2315_pci.patch
index 8009da0684..6623dabf32 100644
--- a/target/linux/atheros/patches-3.14/105-ar2315_pci.patch
+++ b/target/linux/atheros/patches-3.14/105-ar2315_pci.patch
@@ -7,7 +7,7 @@
+obj-$(CONFIG_ATHEROS_AR2315_PCI) += pci.o
--- /dev/null
+++ b/arch/mips/ar231x/pci.c
-@@ -0,0 +1,336 @@
+@@ -0,0 +1,350 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
@@ -65,55 +65,64 @@
+#define AR2315_MEM_SIZE 0x00ffffffUL
+#define AR2315_IO_SIZE 0x00007fffUL
+
++/* Arbitrary size of memory region to access the configuration space */
++#define AR2315_PCI_CFG_SIZE 0x00100000
++
+#define AR2315_PCI_HOST_SLOT 3
+#define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS)
+
-+static unsigned long configspace;
++static void __iomem *ar2315_pci_cfg_mem;
+
+static int ar2315_pci_cfg_access(int devfn, int where, int size, u32 *ptr,
+ bool write)
+{
+ int func = PCI_FUNC(devfn);
+ int dev = PCI_SLOT(devfn);
-+ u32 value = 0;
-+ int err = 0;
-+ u32 addr;
++ u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3);
++ u32 mask = 0xffffffff >> 8 * (4 - size);
++ u32 sh = (where & 3) * 8;
++ u32 value, isr;
++
++ /* Prevent access past the remapped area */
++ if (addr >= AR2315_PCI_CFG_SIZE || dev > 18)
++ return PCIBIOS_DEVICE_NOT_FOUND;
+
++ /* Clear pending errors */
++ ar231x_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ /* Select Configuration access */
+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL);
-+ mb();
+
-+ addr = (u32)configspace + (1 << (13 + dev)) + (func << 8) + where;
-+ if (size == 1)
-+ addr ^= 0x3;
-+ else if (size == 2)
-+ addr ^= 0x2;
++ mb(); /* PCI must see space change before we begin */
++
++ value = __raw_readl(ar2315_pci_cfg_mem + addr);
++
++ isr = ar231x_read_reg(AR2315_PCI_ISR);
++ if (isr & AR2315_PCI_INT_ABORT)
++ goto exit_err;
+
+ if (write) {
-+ value = *ptr;
-+ if (size == 1)
-+ err = put_dbe(value, (u8 *)addr);
-+ else if (size == 2)
-+ err = put_dbe(value, (u16 *)addr);
-+ else if (size == 4)
-+ err = put_dbe(value, (u32 *)addr);
++ value = (value & ~(mask << sh)) | *ptr << sh;
++ __raw_writel(value, ar2315_pci_cfg_mem + addr);
++ isr = ar231x_read_reg(AR2315_PCI_ISR);
++ if (isr & AR2315_PCI_INT_ABORT)
++ goto exit_err;
+ } else {
-+ if (size == 1)
-+ err = get_dbe(value, (u8 *)addr);
-+ else if (size == 2)
-+ err = get_dbe(value, (u16 *)addr);
-+ else if (size == 4)
-+ err = get_dbe(value, (u32 *)addr);
-+ if (err)
-+ *ptr = 0xffffffff;
-+ else
-+ *ptr = value;
++ *ptr = (value >> sh) & mask;
+ }
+
++ goto exit;
++
++exit_err:
++ ar231x_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
++ if (!write)
++ *ptr = 0xffffffff;
++
++exit:
+ /* Select Memory access */
+ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0);
+
-+ return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++ return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND :
++ PCIBIOS_SUCCESSFUL;
+}
+
+static inline int ar2315_pci_local_cfg_rd(unsigned devfn, int where, u32 *val)
@@ -129,7 +138,7 @@
+static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
-+ if ((PCI_SLOT(devfn) != 0) || (PCI_FUNC(devfn) > 2))
++ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, value, 0);
@@ -138,7 +147,7 @@
+static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
-+ if ((PCI_SLOT(devfn) != 0) || (PCI_FUNC(devfn) > 2))
++ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, &value, 1);
@@ -282,8 +291,13 @@
+ return -ENODEV;
+
+ /* Remap PCI config space */
-+ configspace = (unsigned long)ioremap_nocache(AR2315_PCIEXT,
-+ 1 * 1024 * 1024);
++ ar2315_pci_cfg_mem = ioremap_nocache(AR2315_PCIEXT,
++ AR2315_PCI_CFG_SIZE);
++ if (!ar2315_pci_cfg_mem) {
++ pr_err("ar2315-pci: failed to remap PCI config space\n");
++ return -ENOMEM;
++ }
++
+ ar2315_pci_controller.io_map_base =
+ (unsigned long)ioremap_nocache(AR2315_MEM_BASE +
+ AR2315_MEM_SIZE, AR2315_IO_SIZE);
@@ -339,7 +353,7 @@
+ return 0;
+
+error:
-+ iounmap((void __iomem *)configspace);
++ iounmap(ar2315_pci_cfg_mem);
+ return res;
+}
+