summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/access.c87
-rw-r--r--drivers/pci/host/pci-host-generic.c51
-rw-r--r--drivers/pci/host/pci-rcar-gen2.c51
-rw-r--r--drivers/pci/host/pci-tegra.c55
-rw-r--r--drivers/pci/host/pci-xgene.c150
-rw-r--r--drivers/pci/host/pcie-xilinx.c88
6 files changed, 114 insertions, 368 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 49dd766852ba..d9b64a175990 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -67,6 +67,93 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
+int pci_generic_config_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ void __iomem *addr;
+
+ addr = bus->ops->map_bus(bus, devfn, where);
+ if (!addr) {
+ *val = ~0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ if (size == 1)
+ *val = readb(addr);
+ else if (size == 2)
+ *val = readw(addr);
+ else
+ *val = readl(addr);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_generic_config_read);
+
+int pci_generic_config_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ void __iomem *addr;
+
+ addr = bus->ops->map_bus(bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ writeb(val, addr);
+ else if (size == 2)
+ writew(val, addr);
+ else
+ writel(val, addr);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_generic_config_write);
+
+int pci_generic_config_read32(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ void __iomem *addr;
+
+ addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
+ if (!addr) {
+ *val = ~0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ *val = readl(addr);
+
+ if (size <= 2)
+ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_generic_config_read32);
+
+int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ void __iomem *addr;
+ u32 mask, tmp;
+
+ addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 4) {
+ writel(val, addr);
+ return PCIBIOS_SUCCESSFUL;
+ } else {
+ mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
+ }
+
+ tmp = readl(addr) & mask;
+ tmp |= val << ((where & 0x3) * 8);
+ writel(tmp, addr);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_generic_config_write32);
+
/**
* pci_bus_set_ops - Set raw operations of pci bus
* @bus: pci bus struct
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 6eb1aa75bd37..925e29e3d4c8 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -76,55 +76,9 @@ static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = {
.map_bus = gen_pci_map_cfg_bus_ecam,
};
-static int gen_pci_config_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *val)
-{
- void __iomem *addr;
- struct pci_sys_data *sys = bus->sysdata;
- struct gen_pci *pci = sys->private_data;
-
- addr = pci->cfg.ops->map_bus(bus, devfn, where);
-
- switch (size) {
- case 1:
- *val = readb(addr);
- break;
- case 2:
- *val = readw(addr);
- break;
- default:
- *val = readl(addr);
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int gen_pci_config_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- void __iomem *addr;
- struct pci_sys_data *sys = bus->sysdata;
- struct gen_pci *pci = sys->private_data;
-
- addr = pci->cfg.ops->map_bus(bus, devfn, where);
-
- switch (size) {
- case 1:
- writeb(val, addr);
- break;
- case 2:
- writew(val, addr);
- break;
- default:
- writel(val, addr);
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
static struct pci_ops gen_pci_ops = {
- .read = gen_pci_config_read,
- .write = gen_pci_config_write,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
};
static const struct of_device_id gen_pci_of_match[] = {
@@ -287,6 +241,7 @@ static int gen_pci_probe(struct platform_device *pdev)
of_id = of_match_node(gen_pci_of_match, np);
pci->cfg.ops = of_id->data;
+ gen_pci_ops.map_bus = pci->cfg.ops->map_bus;
pci->host.dev.parent = dev;
INIT_LIST_HEAD(&pci->host.windows);
INIT_LIST_HEAD(&pci->resources);
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index d9c042febb1a..dd6b84e6206c 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -131,52 +131,6 @@ static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
return priv->reg + (slot >> 1) * 0x100 + where;
}
-static int rcar_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *val)
-{
- void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where);
-
- if (!reg)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- switch (size) {
- case 1:
- *val = ioread8(reg);
- break;
- case 2:
- *val = ioread16(reg);
- break;
- default:
- *val = ioread32(reg);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where);
-
- if (!reg)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- switch (size) {
- case 1:
- iowrite8(val, reg);
- break;
- case 2:
- iowrite16(val, reg);
- break;
- default:
- iowrite32(val, reg);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
/* PCI interrupt mapping */
static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -325,8 +279,9 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
}
static struct pci_ops rcar_pci_ops = {
- .read = rcar_pci_read_config,
- .write = rcar_pci_write_config,
+ .map_bus = rcar_pci_cfg_base,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
};
static int rcar_pci_probe(struct platform_device *pdev)
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 6f9c29fa70e7..00e92720d7f7 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -480,59 +480,10 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
return addr;
}
-static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *value)
-{
- void __iomem *addr;
-
- addr = tegra_pcie_conf_address(bus, devfn, where);
- if (!addr) {
- *value = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- *value = readl(addr);
-
- if (size == 1)
- *value = (*value >> (8 * (where & 3))) & 0xff;
- else if (size == 2)
- *value = (*value >> (8 * (where & 3))) & 0xffff;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 value)
-{
- void __iomem *addr;
- u32 mask, tmp;
-
- addr = tegra_pcie_conf_address(bus, devfn, where);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (size == 4) {
- writel(value, addr);
- return PCIBIOS_SUCCESSFUL;
- }
-
- if (size == 2)
- mask = ~(0xffff << ((where & 0x3) * 8));
- else if (size == 1)
- mask = ~(0xff << ((where & 0x3) * 8));
- else
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- tmp = readl(addr) & mask;
- tmp |= value << ((where & 0x3) * 8);
- writel(tmp, addr);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
static struct pci_ops tegra_pcie_ops = {
- .read = tegra_pcie_read_conf,
- .write = tegra_pcie_write_conf,
+ .map_bus = tegra_pcie_conf_address,
+ .read = pci_generic_config_read32,
+ .write = pci_generic_config_write32,
};
static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index fdb348d3ccd3..e77d831dc241 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -74,92 +74,6 @@ static inline u32 pcie_bar_low_val(u32 addr, u32 flags)
return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags;
}
-/* PCIe Configuration Out/In */
-static inline void xgene_pcie_cfg_out32(void __iomem *addr, int offset, u32 val)
-{
- writel(val, addr + offset);
-}
-
-static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val)
-{
- u32 val32 = readl(addr + (offset & ~0x3));
-
- switch (offset & 0x3) {
- case 2:
- val32 &= ~0xFFFF0000;
- val32 |= (u32)val << 16;
- break;
- case 0:
- default:
- val32 &= ~0xFFFF;
- val32 |= val;
- break;
- }
- writel(val32, addr + (offset & ~0x3));
-}
-
-static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val)
-{
- u32 val32 = readl(addr + (offset & ~0x3));
-
- switch (offset & 0x3) {
- case 0:
- val32 &= ~0xFF;
- val32 |= val;
- break;
- case 1:
- val32 &= ~0xFF00;
- val32 |= (u32)val << 8;
- break;
- case 2:
- val32 &= ~0xFF0000;
- val32 |= (u32)val << 16;
- break;
- case 3:
- default:
- val32 &= ~0xFF000000;
- val32 |= (u32)val << 24;
- break;
- }
- writel(val32, addr + (offset & ~0x3));
-}
-
-static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val)
-{
- *val = readl(addr + offset);
-}
-
-static inline void xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val)
-{
- *val = readl(addr + (offset & ~0x3));
-
- switch (offset & 0x3) {
- case 2:
- *val >>= 16;
- break;
- }
-
- *val &= 0xFFFF;
-}
-
-static inline void xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val)
-{
- *val = readl(addr + (offset & ~0x3));
-
- switch (offset & 0x3) {
- case 3:
- *val = *val >> 24;
- break;
- case 2:
- *val = *val >> 16;
- break;
- case 1:
- *val = *val >> 8;
- break;
- }
- *val &= 0xFF;
-}
-
/*
* When the address bit [17:16] is 2'b01, the Configuration access will be
* treated as Type 1 and it will be forwarded to external PCIe device.
@@ -213,69 +127,23 @@ static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
return false;
}
-static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct xgene_pcie_port *port = bus->sysdata;
- void __iomem *addr;
-
- if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (xgene_pcie_hide_rc_bars(bus, offset)) {
- *val = 0;
- return PCIBIOS_SUCCESSFUL;
- }
-
- xgene_pcie_set_rtdid_reg(bus, devfn);
- addr = xgene_pcie_get_cfg_base(bus);
- switch (len) {
- case 1:
- xgene_pcie_cfg_in8(addr, offset, val);
- break;
- case 2:
- xgene_pcie_cfg_in16(addr, offset, val);
- break;
- default:
- xgene_pcie_cfg_in32(addr, offset, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int xgene_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
+static int xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int offset)
{
struct xgene_pcie_port *port = bus->sysdata;
- void __iomem *addr;
- if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (xgene_pcie_hide_rc_bars(bus, offset))
- return PCIBIOS_SUCCESSFUL;
+ if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up ||
+ xgene_pcie_hide_rc_bars(bus, offset))
+ return NULL;
xgene_pcie_set_rtdid_reg(bus, devfn);
- addr = xgene_pcie_get_cfg_base(bus);
- switch (len) {
- case 1:
- xgene_pcie_cfg_out8(addr, offset, (u8)val);
- break;
- case 2:
- xgene_pcie_cfg_out16(addr, offset, (u16)val);
- break;
- default:
- xgene_pcie_cfg_out32(addr, offset, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
+ return xgene_pcie_get_cfg_base(bus);
}
static struct pci_ops xgene_pcie_ops = {
- .read = xgene_pcie_read_config,
- .write = xgene_pcie_write_config
+ .map_bus = xgene_pcie_map_bus,
+ .read = pci_generic_config_read32,
+ .write = pci_generic_config_write32,
};
static u64 xgene_pcie_set_ib_mask(void __iomem *csr_base, u32 addr,
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index ce1c61d85b2c..eac4a4b957ca 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -189,7 +189,7 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
}
/**
- * xilinx_pcie_config_base - Get configuration base
+ * xilinx_pcie_map_bus - Get configuration base
* @bus: PCI Bus structure
* @devfn: Device/function
* @where: Offset from base
@@ -197,96 +197,26 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
* Return: Base address of the configuration space needed to be
* accessed.
*/
-static void __iomem *xilinx_pcie_config_base(struct pci_bus *bus,
- unsigned int devfn, int where)
+static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,
+ unsigned int devfn, int where)
{
struct xilinx_pcie_port *port = sys_to_pcie(bus->sysdata);
int relbus;
+ if (!xilinx_pcie_valid_device(bus, devfn))
+ return NULL;
+
relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |
(devfn << ECAM_DEV_NUM_SHIFT);
return port->reg_base + relbus + where;
}
-/**
- * xilinx_pcie_read_config - Read configuration space
- * @bus: PCI Bus structure
- * @devfn: Device/function
- * @where: Offset from base
- * @size: Byte/word/dword
- * @val: Value to be read
- *
- * Return: PCIBIOS_SUCCESSFUL on success
- * PCIBIOS_DEVICE_NOT_FOUND on failure
- */
-static int xilinx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *val)
-{
- void __iomem *addr;
-
- if (!xilinx_pcie_valid_device(bus, devfn)) {
- *val = 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- addr = xilinx_pcie_config_base(bus, devfn, where);
-
- switch (size) {
- case 1:
- *val = readb(addr);
- break;
- case 2:
- *val = readw(addr);
- break;
- default:
- *val = readl(addr);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/**
- * xilinx_pcie_write_config - Write configuration space
- * @bus: PCI Bus structure
- * @devfn: Device/function
- * @where: Offset from base
- * @size: Byte/word/dword
- * @val: Value to be written to device
- *
- * Return: PCIBIOS_SUCCESSFUL on success
- * PCIBIOS_DEVICE_NOT_FOUND on failure
- */
-static int xilinx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- void __iomem *addr;
-
- if (!xilinx_pcie_valid_device(bus, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = xilinx_pcie_config_base(bus, devfn, where);
-
- switch (size) {
- case 1:
- writeb(val, addr);
- break;
- case 2:
- writew(val, addr);
- break;
- default:
- writel(val, addr);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
/* PCIe operations */
static struct pci_ops xilinx_pcie_ops = {
- .read = xilinx_pcie_read_config,
- .write = xilinx_pcie_write_config,
+ .map_bus = xilinx_pcie_map_bus,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
};
/* MSI functions */