Commit 2cd59dea authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/config' into next

* pci/config:
  PCI: xilinx: Convert to use generic config accessors
  PCI: xgene: Convert to use generic config accessors
  PCI: tegra: Convert to use generic config accessors
  PCI: rcar: Convert to use generic config accessors
  PCI: generic: Convert to use generic config accessors
  powerpc/powermac: Convert PCI to use generic config accessors
  powerpc/fsl_pci: Convert PCI to use generic config accessors
  ARM: ks8695: Convert PCI to use generic config accessors
  ARM: sa1100: Convert PCI to use generic config accessors
  ARM: integrator: Convert PCI to use generic config accessors
  ARM: cns3xxx: Convert PCI to use generic config accessors
  PCI: Add generic config accessors
  powerpc/PCI: Add struct pci_ops member names to initialization
  mn10300/PCI: Add struct pci_ops member names to initialization
  MIPS: PCI: Add struct pci_ops member names to initialization
  frv/PCI: Add struct pci_ops member names to initialization
parents 341f3a2b 029e2151
......@@ -51,8 +51,8 @@ static struct cns3xxx_pcie *pbus_to_cnspci(struct pci_bus *bus)
return sysdata_to_cnspci(bus->sysdata);
}
static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
unsigned int devfn, int where)
static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus);
int busno = bus->number;
......@@ -88,55 +88,22 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
u32 v;
void __iomem *base;
int ret;
u32 mask = (0x1ull << (size * 8)) - 1;
int shift = (where % 4) * 8;
base = cns3xxx_pci_cfg_base(bus, devfn, where);
if (!base) {
*val = 0xffffffff;
return PCIBIOS_SUCCESSFUL;
}
v = __raw_readl(base);
ret = pci_generic_config_read32(bus, devfn, where, size, val);
if (bus->number == 0 && devfn == 0 &&
(where & 0xffc) == PCI_CLASS_REVISION) {
if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn &&
(where & 0xffc) == PCI_CLASS_REVISION)
/*
* RC's class is 0xb, but Linux PCI driver needs 0x604
* for a PCIe bridge. So we must fixup the class code
* to 0x604 here.
*/
v &= 0xff;
v |= 0x604 << 16;
}
*val = (v >> shift) & mask;
return PCIBIOS_SUCCESSFUL;
}
static int cns3xxx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
u32 v;
void __iomem *base;
u32 mask = (0x1ull << (size * 8)) - 1;
int shift = (where % 4) * 8;
base = cns3xxx_pci_cfg_base(bus, devfn, where);
if (!base)
return PCIBIOS_SUCCESSFUL;
v = __raw_readl(base);
v &= ~(mask << shift);
v |= (val & mask) << shift;
__raw_writel(v, base);
*val = ((((*val << shift) & 0xff) | (0x604 << 16)) >> shift) & mask;
return PCIBIOS_SUCCESSFUL;
return ret;
}
static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys)
......@@ -155,8 +122,9 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys)
}
static struct pci_ops cns3xxx_pcie_ops = {
.map_bus = cns3xxx_pci_map_bus,
.read = cns3xxx_pci_read_config,
.write = cns3xxx_pci_write_config,
.write = pci_generic_config_write,
};
static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
......@@ -356,7 +356,6 @@ static u64 pre_mem_pci_sz;
* 7:2 register number
*
*/
static DEFINE_RAW_SPINLOCK(v3_lock);
#undef V3_LB_BASE_PREFETCH
#define V3_LB_BASE_PREFETCH 0
......@@ -457,67 +456,21 @@ static void v3_close_config_window(void)
static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
void __iomem *addr;
unsigned long flags;
u32 v;
raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
case 1:
v = __raw_readb(addr);
break;
case 2:
v = __raw_readw(addr);
break;
default:
v = __raw_readl(addr);
break;
}
int ret = pci_generic_config_read(bus, devfn, where, size, val);
v3_close_config_window();
raw_spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
return ret;
}
static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
void __iomem *addr;
unsigned long flags;
raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
case 1:
__raw_writeb((u8)val, addr);
__raw_readb(addr);
break;
case 2:
__raw_writew((u16)val, addr);
__raw_readw(addr);
break;
case 4:
__raw_writel(val, addr);
__raw_readl(addr);
break;
}
int ret = pci_generic_config_write(bus, devfn, where, size, val);
v3_close_config_window();
raw_spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
return ret;
}
static struct pci_ops pci_v3_ops = {
.map_bus = v3_open_config_window,
.read = v3_read_config,
.write = v3_write_config,
};
......@@ -658,7 +611,6 @@ static int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
*/
static void __init pci_v3_preinit(void)
{
unsigned long flags;
unsigned int temp;
phys_addr_t io_address = pci_pio_to_address(io_mem.start);
......@@ -672,8 +624,6 @@ static void __init pci_v3_preinit(void)
hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
raw_spin_lock_irqsave(&v3_lock, flags);
/*
* Unlock V3 registers, but only if they were previously locked.
*/
......@@ -736,8 +686,6 @@ static void __init pci_v3_preinit(void)
v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
v3_writeb(V3_LB_IMASK, 0x28);
__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
raw_spin_unlock_irqrestore(&v3_lock, flags);
}
static void __init pci_v3_postinit(void)
......
......@@ -38,8 +38,6 @@
static int pci_dbg;
static int pci_cfg_dbg;
static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where)
{
......@@ -59,75 +57,11 @@ static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsi
}
}
/*
* The KS8695 datasheet prohibits anything other than 32bit accesses
* to the IO registers, so all our configuration must be done with
* 32bit operations, and the correct bit masking and shifting.
*/
static int ks8695_pci_readconfig(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *value)
{
ks8695_pci_setupconfig(bus->number, devfn, where);
*value = __raw_readl(KS8695_PCI_VA + KS8695_PBCD);
switch (size) {
case 4:
break;
case 2:
*value = *value >> ((where & 2) * 8);
*value &= 0xffff;
break;
case 1:
*value = *value >> ((where & 3) * 8);
*value &= 0xff;
break;
}
if (pci_cfg_dbg) {
printk("read: %d,%08x,%02x,%d: %08x (%08x)\n",
bus->number, devfn, where, size, *value,
__raw_readl(KS8695_PCI_VA + KS8695_PBCD));
}
return PCIBIOS_SUCCESSFUL;
}
static int ks8695_pci_writeconfig(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 value)
static void __iomem *ks8695_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
int where)
{
unsigned long tmp;
if (pci_cfg_dbg) {
printk("write: %d,%08x,%02x,%d: %08x\n",
bus->number, devfn, where, size, value);
}
ks8695_pci_setupconfig(bus->number, devfn, where);
switch (size) {
case 4:
__raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
break;
case 2:
tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD);
tmp &= ~(0xffff << ((where & 2) * 8));
tmp |= value << ((where & 2) * 8);
__raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD);
break;
case 1:
tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD);
tmp &= ~(0xff << ((where & 3) * 8));
tmp |= value << ((where & 3) * 8);
__raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD);
break;
}
return PCIBIOS_SUCCESSFUL;
return KS8695_PCI_VA + KS8695_PBCD;
}
static void ks8695_local_writeconfig(int where, u32 value)
......@@ -137,8 +71,9 @@ static void ks8695_local_writeconfig(int where, u32 value)
}
static struct pci_ops ks8695_pci_ops = {
.read = ks8695_pci_readconfig,
.write = ks8695_pci_writeconfig,
.map_bus = ks8695_pci_map_bus,
.read = pci_generic_config_read32,
.write = pci_generic_config_write32,
};
static struct resource pci_mem = {
......
......@@ -22,7 +22,6 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
......@@ -30,97 +29,20 @@
#include <mach/nanoengine.h>
#include <mach/hardware.h>
static DEFINE_SPINLOCK(nano_lock);
static int nanoengine_get_pci_address(struct pci_bus *bus,
unsigned int devfn, int where, void __iomem **address)
static void __iomem *nanoengine_pci_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
int ret = PCIBIOS_DEVICE_NOT_FOUND;
unsigned int busnr = bus->number;
if (bus->number != 0 || (devfn >> 3) != 0)
return NULL;
*address = (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT +
return (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT +
((bus->number << 16) | (devfn << 8) | (where & ~3));
ret = (busnr > 255 || devfn > 255 || where > 255) ?
PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
return ret;
}
static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
int ret;
void __iomem *address;
unsigned long flags;
u32 v;
/* nanoEngine PCI bridge does not return -1 for a non-existing
* device. We must fake the answer. We know that the only valid
* device is device zero at bus 0, which is the network chip. */
if (bus->number != 0 || (devfn >> 3) != 0) {
v = -1;
nanoengine_get_pci_address(bus, devfn, where, &address);
goto exit_function;
}
spin_lock_irqsave(&nano_lock, flags);
ret = nanoengine_get_pci_address(bus, devfn, where, &address);
if (ret != PCIBIOS_SUCCESSFUL)
return ret;
v = __raw_readl(address);
spin_unlock_irqrestore(&nano_lock, flags);
v >>= ((where & 3) * 8);
v &= (unsigned long)(-1) >> ((4 - size) * 8);
exit_function:
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
int ret;
void __iomem *address;
unsigned long flags;
unsigned shift;
u32 v;
shift = (where & 3) * 8;
spin_lock_irqsave(&nano_lock, flags);
ret = nanoengine_get_pci_address(bus, devfn, where, &address);
if (ret != PCIBIOS_SUCCESSFUL)
return ret;
v = __raw_readl(address);
switch (size) {
case 1:
v &= ~(0xFF << shift);
v |= val << shift;
break;
case 2:
v &= ~(0xFFFF << shift);
v |= val << shift;
break;
case 4:
v = val;
break;
}
__raw_writel(v, address);
spin_unlock_irqrestore(&nano_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops pci_nano_ops = {
.read = nanoengine_read_config,
.write = nanoengine_write_config,
.map_bus = nanoengine_pci_map_bus,
.read = pci_generic_config_read32,
.write = pci_generic_config_write32,
};
static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot,
......
......@@ -168,8 +168,8 @@ static int pci_frv_write_config(struct pci_bus *bus, unsigned int devfn, int whe
}
static struct pci_ops pci_direct_frv = {
pci_frv_read_config,
pci_frv_write_config,
.read = pci_frv_read_config,
.write = pci_frv_write_config,
};
/*
......
......@@ -173,8 +173,8 @@ static int bcm1480_pcibios_write(struct pci_bus *bus, unsigned int devfn,
}
struct pci_ops bcm1480_pci_ops = {
bcm1480_pcibios_read,
bcm1480_pcibios_write,
.read = bcm1480_pcibios_read,
.write = bcm1480_pcibios_write,
};
static struct resource bcm1480_mem_resource = {
......
......@@ -327,8 +327,8 @@ static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
static struct pci_ops octeon_pci_ops = {
octeon_read_config,
octeon_write_config,
.read = octeon_read_config,
.write = octeon_write_config,
};
static struct resource octeon_pci_mem_resource = {
......
......@@ -1792,8 +1792,8 @@ static int octeon_dummy_write_config(struct pci_bus *bus, unsigned int devfn,
}
static struct pci_ops octeon_pcie0_ops = {
octeon_pcie0_read_config,
octeon_pcie0_write_config,
.read = octeon_pcie0_read_config,
.write = octeon_pcie0_write_config,
};
static struct resource octeon_pcie0_mem_resource = {
......@@ -1813,8 +1813,8 @@ static struct pci_controller octeon_pcie0_controller = {
};
static struct pci_ops octeon_pcie1_ops = {
octeon_pcie1_read_config,
octeon_pcie1_write_config,
.read = octeon_pcie1_read_config,
.write = octeon_pcie1_write_config,
};
static struct resource octeon_pcie1_mem_resource = {
......@@ -1834,8 +1834,8 @@ static struct pci_controller octeon_pcie1_controller = {
};
static struct pci_ops octeon_dummy_ops = {
octeon_dummy_read_config,
octeon_dummy_write_config,
.read = octeon_dummy_read_config,
.write = octeon_dummy_write_config,
};
static struct resource octeon_dummy_mem_resource = {
......
......@@ -228,8 +228,8 @@ static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn,
}
static struct pci_ops pci_direct_ampci = {
pci_ampci_read_config,
pci_ampci_write_config,
.read = pci_ampci_read_config,
.write = pci_ampci_write_config,
};
/*
......
......@@ -399,8 +399,8 @@ static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
}
static struct pci_ops scc_pciex_pci_ops = {
scc_pciex_read_config,
scc_pciex_write_config,
.read = scc_pciex_read_config,
.write = scc_pciex_write_config,
};
static void pciex_clear_intr_all(unsigned int __iomem *base)
......
......@@ -133,17 +133,23 @@ static void __init fixup_bus_range(struct device_node *bridge)
|(((unsigned int)(off)) & 0xFCUL) \
|1UL)
static volatile void __iomem *macrisc_cfg_access(struct pci_controller* hose,
u8 bus, u8 dev_fn, u8 offset)
static void __iomem *macrisc_cfg_map_bus(struct pci_bus *bus,
unsigned int dev_fn,
int offset)
{
unsigned int caddr;
struct pci_controller *hose;
if (bus == hose->first_busno) {
hose = pci_bus_to_host(bus);
if (hose == NULL)
return NULL;
if (bus->number == hose->first_busno) {
if (dev_fn < (11 << 3))
return NULL;
caddr = MACRISC_CFA0(dev_fn, offset);
} else
caddr = MACRISC_CFA1(bus, dev_fn, offset);
caddr = MACRISC_CFA1(bus->number, dev_fn, offset);
/* Uninorth will return garbage if we don't read back the value ! */
do {
......@@ -154,129 +160,46 @@ static volatile void __iomem *macrisc_cfg_access(struct pci_controller* hose,
return hose->cfg_data + offset;
}
static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
struct pci_controller *hose;
volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
if (offset >= 0x100)
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
*val = in_8(addr);
break;
case 2:
*val = in_le16(addr);
break;
default:
*val = in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose;
volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
if (offset >= 0x100)
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
out_8(addr, val);
break;
case 2:
out_le16(addr, val);
break;
default:
out_le32(addr, val);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops macrisc_pci_ops =
{
.read = macrisc_read_config,
.write = macrisc_write_config,
.map_bus = macrisc_cfg_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
#ifdef CONFIG_PPC32
/*
* Verify that a specific (bus, dev_fn) exists on chaos
*/
static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
static void __iomem *chaos_map_bus(struct pci_bus *bus, unsigned int devfn,
int offset)
{
struct device_node *np;
const u32 *vendor, *device;
if (offset >= 0x100)
return PCIBIOS_BAD_REGISTER_NUMBER;
return NULL;
np = of_pci_find_child_device(bus->dev.of_node, devfn);
if (np == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
return NULL;
vendor = of_get_property(np, "vendor-id", NULL);
device = of_get_property(np, "device-id", NULL);
if (vendor == NULL || device == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
return NULL;
if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)
&& (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))
return PCIBIOS_BAD_REGISTER_NUMBER;
return PCIBIOS_SUCCESSFUL;
}
return NULL;
static int
chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
int result = chaos_validate_dev(bus, devfn, offset);
if (result == PCIBIOS_BAD_REGISTER_NUMBER)
*val = ~0U;
if (result != PCIBIOS_SUCCESSFUL)
return result;
return macrisc_read_config(bus, devfn, offset, len, val);
}
static int
chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
int result = chaos_validate_dev(bus, devfn, offset);
if (result != PCIBIOS_SUCCESSFUL)
return result;
return macrisc_write_config(bus, devfn, offset, len, val);
return macrisc_cfg_map_bus(bus, devfn, offset);
}
static struct pci_ops chaos_pci_ops =
{
.read = chaos_read_config,
.write = chaos_write_config,
.map_bus = chaos_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
static void __init setup_chaos(struct pci_controller *hose,
......@@ -471,15 +394,24 @@ static struct pci_ops u3_ht_pci_ops =
|(((unsigned int)(off)) & 0xfcU) \
|1UL)
static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,
u8 bus, u8 dev_fn, int offset)
static void __iomem *u4_pcie_cfg_map_bus(struct pci_bus *bus,
unsigned int dev_fn,
int offset)
{
struct pci_controller *hose;
unsigned int caddr;
if (bus == hose->first_busno) {
if (offset >= 0x1000)
return NULL;
hose = pci_bus_to_host(bus);
if (!hose)
return NULL;
if (bus->number == hose->first_busno) {
caddr = U4_PCIE_CFA0(dev_fn, offset);
} else
caddr = U4_PCIE_CFA1(bus, dev_fn, offset);
caddr = U4_PCIE_CFA1(bus->number, dev_fn, offset);
/* Uninorth will return garbage if we don't read back the value ! */
do {
......@@ -490,74 +422,11 @@ static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,
return hose->cfg_data + offset;
}
static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
struct pci_controller *hose;
volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
if (offset >= 0x1000)
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
*val = in_8(addr);
break;
case 2:
*val = in_le16(addr);
break;
default:
*val = in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose;
volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
if (offset >= 0x1000)
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
out_8(addr, val);
break;
case 2:
out_le16(addr, val);
break;
default:
out_le32(addr, val);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops u4_pcie_pci_ops =
{
.read = u4_pcie_read_config,
.write = u4_pcie_write_config,
.map_bus = u4_pcie_cfg_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
static void pmac_pci_fixup_u4_of_node(struct pci_dev *dev)
......
......@@ -645,61 +645,21 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
return pcie->cfg_type1 + offset;
}
static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
void __iomem *cfg_addr;
cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
if (!cfg_addr)
return PCIBIOS_DEVICE_NOT_FOUND;
switch (len) {
case 1:
*val = in_8(cfg_addr);
break;
case 2:
*val = in_le16(cfg_addr);
break;
default:
*val = in_le32(cfg_addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose = pci_bus_to_host(bus);
void __iomem *cfg_addr;
cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
if (!cfg_addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */
if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno)
val &= 0xffffff00;
switch (len) {
case 1:
out_8(cfg_addr, val);
break;
case 2:
out_le16(cfg_addr, val);
break;
default:
out_le32(cfg_addr, val);
break;
}
return PCIBIOS_SUCCESSFUL;
return pci_generic_config_write(bus, devfn, offset, len, val);
}
static struct pci_ops mpc83xx_pcie_ops = {
.read = mpc83xx_pcie_read_config,
.map_bus = mpc83xx_pcie_remap_cfg,
.read = pci_generic_config_read,
.write = mpc83xx_pcie_write_config,
};
......
......@@ -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
......
......@@ -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);
......
......@@ -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)
......
......@@ -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)
......
......@@ -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,
......
......@@ -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 */
......
......@@ -564,6 +564,7 @@ static inline int pcibios_err_to_errno(int err)
/* Low-level architecture-dependent routines */
struct pci_ops {
void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where);
int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
};
......@@ -861,6 +862,16 @@ int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
int where, u16 val);
int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
int where, u32 val);
int pci_generic_config_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val);
int pci_generic_config_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val);
int pci_generic_config_read32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val);
int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val);
struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops);
static inline int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment