summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-cns3xxx/pcie.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-05 13:44:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-05 13:44:27 -0700
commit9f800363bb0ea459e15bef0928a72c88d374e489 (patch)
tree13a6b4165d3e2ba18e88e5103437f74e84e0838d /arch/arm/mach-cns3xxx/pcie.c
parent2d1eb87ae1e6f3999e77989fd2f831b134270787 (diff)
parentcb46a256a78225817945cd52068d61d5126c236e (diff)
downloadlinux-9f800363bb0ea459e15bef0928a72c88d374e489.tar.bz2
Merge tag 'fixes-non-critical-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC non-critical bug fixes from Arnd Bergmann: "Lots of isolated bug fixes that were not found to be important enough to be submitted before the merge window or backported into stable kernels. The vast majority of these came out of Arnd's randconfig testing and just prevents running into build-time bugs in configurations that we do not care about in practice" * tag 'fixes-non-critical-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (75 commits) ARM: at91: fix a typo ARM: moxart: fix CPU selection ARM: tegra: fix board DT pinmux setup ARM: nspire: Fix compiler warning IXP4xx: Fix DMA masks. Revert "ARM: ixp4xx: Make dma_set_coherent_mask common, correct implementation" IXP4xx: Fix Goramo Multilink GPIO conversion. Revert "ARM: ixp4xx: fix gpio rework" ARM: tegra: make debug_ll code build for ARMv6 ARM: sunxi: fix build for THUMB2_KERNEL ARM: exynos: add missing include of linux/module.h ARM: exynos: fix l2x0 saved regs handling ARM: samsung: select CRC32 for SAMSUNG_PM_CHECK ARM: samsung: select ATAGS where necessary ARM: samsung: fix SAMSUNG_PM_DEBUG Kconfig logic ARM: samsung: allow serial driver to be disabled ARM: s5pv210: enable IDE support in MACH_TORBRECK ARM: s5p64x0: fix building with only one soc type ARM: s3c64xx: select power domains only when used ARM: s3c64xx: MACH_SMDK6400 needs HSMMC1 ...
Diffstat (limited to 'arch/arm/mach-cns3xxx/pcie.c')
-rw-r--r--arch/arm/mach-cns3xxx/pcie.c105
1 files changed, 32 insertions, 73 deletions
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index c7b204bff386..413134c54452 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -23,15 +23,10 @@
#include "cns3xxx.h"
#include "core.h"
-enum cns3xxx_access_type {
- CNS3XXX_HOST_TYPE = 0,
- CNS3XXX_CFG0_TYPE,
- CNS3XXX_CFG1_TYPE,
- CNS3XXX_NUM_ACCESS_TYPES,
-};
-
struct cns3xxx_pcie {
- struct map_desc cfg_bases[CNS3XXX_NUM_ACCESS_TYPES];
+ void __iomem *host_regs; /* PCI config registers for host bridge */
+ void __iomem *cfg0_regs; /* PCI Type 0 config registers */
+ void __iomem *cfg1_regs; /* PCI Type 1 config registers */
unsigned int irqs[2];
struct resource res_io;
struct resource res_mem;
@@ -66,7 +61,6 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
int busno = bus->number;
int slot = PCI_SLOT(devfn);
int offset;
- enum cns3xxx_access_type type;
void __iomem *base;
/* If there is no link, just show the CNS PCI bridge. */
@@ -78,17 +72,21 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
* we still want to access it. For this to work, we must place
* the first device on the same bus as the CNS PCI bridge.
*/
- if (busno == 0) {
- if (slot > 1)
- return NULL;
- type = slot;
- } else {
- type = CNS3XXX_CFG1_TYPE;
- }
+ if (busno == 0) { /* directly connected PCIe bus */
+ switch (slot) {
+ case 0: /* host bridge device, function 0 only */
+ base = cnspci->host_regs;
+ break;
+ case 1: /* directly connected device */
+ base = cnspci->cfg0_regs;
+ break;
+ default:
+ return NULL; /* no such device */
+ }
+ } else /* remote PCI bus */
+ base = cnspci->cfg1_regs;
- base = (void __iomem *)cnspci->cfg_bases[type].virtual;
offset = ((busno & 0xf) << 20) | (devfn << 12) | (where & 0xffc);
-
return base + offset;
}
@@ -180,36 +178,19 @@ static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct cns3xxx_pcie cns3xxx_pcie[] = {
[0] = {
- .cfg_bases = {
- [CNS3XXX_HOST_TYPE] = {
- .virtual = CNS3XXX_PCIE0_HOST_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE0_HOST_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- [CNS3XXX_CFG0_TYPE] = {
- .virtual = CNS3XXX_PCIE0_CFG0_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG0_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- [CNS3XXX_CFG1_TYPE] = {
- .virtual = CNS3XXX_PCIE0_CFG1_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG1_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- },
+ .host_regs = (void __iomem *)CNS3XXX_PCIE0_HOST_BASE_VIRT,
+ .cfg0_regs = (void __iomem *)CNS3XXX_PCIE0_CFG0_BASE_VIRT,
+ .cfg1_regs = (void __iomem *)CNS3XXX_PCIE0_CFG1_BASE_VIRT,
.res_io = {
.name = "PCIe0 I/O space",
.start = CNS3XXX_PCIE0_IO_BASE,
- .end = CNS3XXX_PCIE0_IO_BASE + SZ_16M - 1,
+ .end = CNS3XXX_PCIE0_CFG0_BASE - 1, /* 16 MiB */
.flags = IORESOURCE_IO,
},
.res_mem = {
.name = "PCIe0 non-prefetchable",
.start = CNS3XXX_PCIE0_MEM_BASE,
- .end = CNS3XXX_PCIE0_MEM_BASE + SZ_16M - 1,
+ .end = CNS3XXX_PCIE0_HOST_BASE - 1, /* 176 MiB */
.flags = IORESOURCE_MEM,
},
.irqs = { IRQ_CNS3XXX_PCIE0_RC, IRQ_CNS3XXX_PCIE0_DEVICE, },
@@ -222,36 +203,19 @@ static struct cns3xxx_pcie cns3xxx_pcie[] = {
},
},
[1] = {
- .cfg_bases = {
- [CNS3XXX_HOST_TYPE] = {
- .virtual = CNS3XXX_PCIE1_HOST_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE1_HOST_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- [CNS3XXX_CFG0_TYPE] = {
- .virtual = CNS3XXX_PCIE1_CFG0_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG0_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- [CNS3XXX_CFG1_TYPE] = {
- .virtual = CNS3XXX_PCIE1_CFG1_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG1_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE,
- },
- },
+ .host_regs = (void __iomem *)CNS3XXX_PCIE1_HOST_BASE_VIRT,
+ .cfg0_regs = (void __iomem *)CNS3XXX_PCIE1_CFG0_BASE_VIRT,
+ .cfg1_regs = (void __iomem *)CNS3XXX_PCIE1_CFG1_BASE_VIRT,
.res_io = {
.name = "PCIe1 I/O space",
.start = CNS3XXX_PCIE1_IO_BASE,
- .end = CNS3XXX_PCIE1_IO_BASE + SZ_16M - 1,
+ .end = CNS3XXX_PCIE1_CFG0_BASE - 1, /* 16 MiB */
.flags = IORESOURCE_IO,
},
.res_mem = {
.name = "PCIe1 non-prefetchable",
.start = CNS3XXX_PCIE1_MEM_BASE,
- .end = CNS3XXX_PCIE1_MEM_BASE + SZ_16M - 1,
+ .end = CNS3XXX_PCIE1_HOST_BASE - 1, /* 176 MiB */
.flags = IORESOURCE_MEM,
},
.irqs = { IRQ_CNS3XXX_PCIE1_RC, IRQ_CNS3XXX_PCIE1_DEVICE, },
@@ -307,18 +271,15 @@ static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
.ops = &cns3xxx_pcie_ops,
.sysdata = &sd,
};
- u32 io_base = cnspci->res_io.start >> 16;
- u32 mem_base = cnspci->res_mem.start >> 16;
- u32 host_base = cnspci->cfg_bases[CNS3XXX_HOST_TYPE].pfn;
- u32 cfg0_base = cnspci->cfg_bases[CNS3XXX_CFG0_TYPE].pfn;
+ u16 mem_base = cnspci->res_mem.start >> 16;
+ u16 mem_limit = cnspci->res_mem.end >> 16;
+ u16 io_base = cnspci->res_io.start >> 16;
+ u16 io_limit = cnspci->res_io.end >> 16;
u32 devfn = 0;
u8 tmp8;
u16 pos;
u16 dc;
- host_base = (__pfn_to_phys(host_base) - 1) >> 16;
- cfg0_base = (__pfn_to_phys(cfg0_base) - 1) >> 16;
-
pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0);
pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1);
pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1);
@@ -328,9 +289,9 @@ static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);
pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base);
- pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, host_base);
+ pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base);
- pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, cfg0_base);
+ pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);
if (!cnspci->linked)
return;
@@ -368,8 +329,6 @@ static int __init cns3xxx_pcie_init(void)
"imprecise external abort");
for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
- iotable_init(cns3xxx_pcie[i].cfg_bases,
- ARRAY_SIZE(cns3xxx_pcie[i].cfg_bases));
cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i));
cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i));
cns3xxx_pcie_check_link(&cns3xxx_pcie[i]);