[PATCH][v2] powerpc/pci: Fix IMMRBAR address
For PEXCSRBAR, bit 3-0 indicate prefetchable and address type. So when getting base address, these bits should be masked, otherwise we may get incorrect base address. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Change log: v2: Use PCI_BASE_ADDRESS_MEM_MASK instead of 0xfff0 arch/powerpc/sysdev/fsl_pci.c | 8 1 file changed, 8 insertions(+) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4dfd61d..252716d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -868,6 +868,14 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose) pci_bus_read_config_dword(hose-bus, PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, base); + + /* +* For PEXCSRBAR, bit 3-0 indicate prefetchable and +* address type. So when getting base address, these +* bits should be masked +*/ + base = PCI_BASE_ADDRESS_MEM_MASK; + return base; } #endif -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 02/12][v4] pci: fsl: add structure fsl_pci
PowerPC uses structure pci_controller to describe PCI controller, but ARM uses structure pci_sys_data. In order to support PowerPC and ARM simultaneously, the patch adds a structure fsl_pci that contains most of the members of the pci_controller and pci_sys_data. Meanwhile, it defines a interface fsl_arch_sys_to_pci() which should be implemented in architecture-specific PCI controller driver to convert pci_controller or pci_sys_data to fsl_pci. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: Added indirect type macro v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ include/linux/fsl/pci-common.h | 48 ++ 1 file changed, 48 insertions(+) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 5e4f683..7ea20a1 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -102,5 +102,53 @@ struct ccsr_pci { }; +/* + * Structure of a PCI controller (host bridge) + */ +struct fsl_pci { + struct list_head node; + bool is_pcie; + struct device_node *dn; + struct device *dev; + + int first_busno; + int last_busno; + int self_busno; + struct resource busn; + + struct pci_ops *ops; + struct ccsr_pci __iomem *regs; + +#define INDIRECT_TYPE_SET_CFG_TYPE 0x0001 +#define INDIRECT_TYPE_EXT_REG 0x0002 +#define INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x0004 +#define INDIRECT_TYPE_NO_PCIE_LINK 0x0008 +#define INDIRECT_TYPE_BIG_ENDIAN 0x0010 +#define INDIRECT_TYPE_BROKEN_MRM 0x0020 +#define INDIRECT_TYPE_FSL_CFG_REG_LINK 0x0040 + u32 indirect_type; + + struct resource io_resource; + resource_size_t io_base_phys; + resource_size_t pci_io_size; + + struct resource mem_resources[3]; + resource_size_t mem_offset[3]; + + int global_number; /* PCI domain number */ + + resource_size_t dma_window_base_cur; + resource_size_t dma_window_size; + + void *sys; +}; + +/* + * Convert architecture specific pci controller structure to fsl_pci + * PowerPC uses structure pci_controller and ARM uses structure pci_sys_data + * to describe pci controller. + */ +extern struct fsl_pci *fsl_arch_sys_to_pci(void *sys); + #endif /* __PCI_COMMON_H */ #endif /* __KERNEL__ */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 03/12][v4] pci: fsl: add PCI indirect access support
The patch adds PCI indirect read/write functions. The main code is ported from arch/powerpc/sysdev/indirect_pci.c. We use general IO API iowrite32be/ioread32be instead of out_be32/in_be32, and use structure fsl_Pci instead of PowerPC's pci_controller. The patch also provides fsl_pcie_check_link() to check PCI link. The weak function fsl_arch_pci_exclude_device() is provided to call ppc_md.pci_exclude_device() for PowerPC architecture. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: moved indirect type macro to header file v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 163 -- include/linux/fsl/pci-common.h| 6 ++ 2 files changed, 145 insertions(+), 24 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 69d338b..d1846ee 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -35,52 +35,167 @@ #include sysdev/fsl_soc.h #include sysdev/fsl_pci.h -static int fsl_pcie_check_link(struct pci_controller *hose) + +int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + return PCIBIOS_SUCCESSFUL; +} + +static int fsl_pci_read_config(struct fsl_pci *pci, int bus, int devfn, + int offset, int len, u32 *val) +{ + u32 bus_no, reg, data; + + if (pci-indirect_type INDIRECT_TYPE_NO_PCIE_LINK) { + if (bus != pci-first_busno) + return PCIBIOS_DEVICE_NOT_FOUND; + if (devfn != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (fsl_arch_pci_exclude_device(pci, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + bus_no = (bus == pci-first_busno) ? pci-self_busno : bus; + + if (pci-indirect_type INDIRECT_TYPE_EXT_REG) + reg = ((offset 0xf00) 16) | (offset 0xfc); + else + reg = offset 0xfc; + + if (pci-indirect_type INDIRECT_TYPE_BIG_ENDIAN) + iowrite32be(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + else + iowrite32(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + + /* +* Note: the caller has already checked that offset is +* suitably aligned and that len is 1, 2 or 4. +*/ + data = ioread32(pci-regs-config_data); + switch (len) { + case 1: + *val = (data (8 * (offset 3))) 0xff; + break; + case 2: + *val = (data (8 * (offset 3))) 0x; + break; + default: + *val = data; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int fsl_pci_write_config(struct fsl_pci *pci, int bus, int devfn, +int offset, int len, u32 val) +{ + void __iomem *cfg_data; + u32 bus_no, reg; + + if (pci-indirect_type INDIRECT_TYPE_NO_PCIE_LINK) { + if (bus != pci-first_busno) + return PCIBIOS_DEVICE_NOT_FOUND; + if (devfn != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (fsl_arch_pci_exclude_device(pci, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + bus_no = (bus == pci-first_busno) ? + pci-self_busno : bus; + + if (pci-indirect_type INDIRECT_TYPE_EXT_REG) + reg = ((offset 0xf00) 16) | (offset 0xfc); + else + reg = offset 0xfc; + + if (pci-indirect_type INDIRECT_TYPE_BIG_ENDIAN) + iowrite32be(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + else + iowrite32(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + + /* suppress setting of PCI_PRIMARY_BUS */ + if (pci-indirect_type INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) + if ((offset == PCI_PRIMARY_BUS) + (bus == pci-first_busno)) + val = 0xff00; + + /* +* Note: the caller has already checked that offset is +* suitably aligned and that len is 1, 2 or 4. +*/ + cfg_data = ((void *) (pci-regs-config_data)) + (offset 3); + switch (len) { + case 1: + iowrite8(val, cfg_data); + break; + case 2: + iowrite16(val, cfg_data); + break; + default: + iowrite32(val, cfg_data); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +bool fsl_pci_check_link(struct fsl_pci *pci) { u32 val = 0
[PATCH 04/12][v4] pci: fsl: add early PCI indirect access support
The driver needs to read/write PCI configuration very early, at that time architecture-specific PCI controller structure and PCI bus have not been created. The patch provides an interface fsl_arch_fake_pci_bus which should be implemented in architecture-specific PCI driver to fake a PCI controller structure and PCI bus. Using the fake PCI controller and PCI bus, the patch provides the early indirect read/write functions. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 26 ++ include/linux/fsl/pci-common.h| 7 +++ 2 files changed, 33 insertions(+) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index d1846ee..a706100 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -198,6 +198,32 @@ static struct pci_ops fsl_indirect_pci_ops = { .write = fsl_indirect_write_config, }; +#define EARLY_FSL_PCI_OP(rw, size, type) \ +int early_fsl_##rw##_config_##size(struct fsl_pci *pci, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_bus_##rw##_config_##size(fsl_arch_fake_pci_bus(pci, bus),\ + devfn, offset, value); \ +} + +EARLY_FSL_PCI_OP(read, byte, u8 *) +EARLY_FSL_PCI_OP(read, word, u16 *) +EARLY_FSL_PCI_OP(read, dword, u32 *) +EARLY_FSL_PCI_OP(write, byte, u8) +EARLY_FSL_PCI_OP(write, word, u16) +EARLY_FSL_PCI_OP(write, dword, u32) + +static int early_fsl_find_capability(struct fsl_pci *pci, +int busnr, int devfn, int cap) +{ + struct pci_bus *bus = fsl_arch_fake_pci_bus(pci, busnr); + + if (!bus) + return 0; + + return pci_bus_find_capability(bus, devfn, cap); +} + static int setup_one_atmu(struct ccsr_pci __iomem *pci, unsigned int index, const struct resource *res, resource_size_t offset) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 726f27b..fd6c497 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -156,5 +156,12 @@ bool fsl_pci_check_link(struct fsl_pci *pci); /* To avoid touching specified devices */ int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn); +/* + * To fake a PCI bus + * it is called by early_fsl_*(), at that time the architecture-dependent + * pci controller and pci bus have not been created. + */ +extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr); + #endif /* __PCI_COMMON_H */ #endif /* __KERNEL__ */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 01/12][v4] pci: fsl: derive the common PCI driver to drivers/pci/host
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pci-fsl-common.c and leaves the architecture specific functions which should be implemented in arch related files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v2-v4: no change v1-v2: 1. rename pci.h to pci-common.h 2. rename pci-fsl.c to pci-fsl-common.c Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 521 +- arch/powerpc/sysdev/fsl_pci.h | 89 .../fsl_pci.c = drivers/pci/host/pci-fsl-common.c | 592 + .../fsl_pci.h = include/linux/fsl/pci-common.h| 45 +- 4 files changed, 7 insertions(+), 1240 deletions(-) copy arch/powerpc/sysdev/fsl_pci.c = drivers/pci/host/pci-fsl-common.c (54%) copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci-common.h (79%) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4dfd61d..0764385 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -27,6 +27,7 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/fsl/pci-common.h #include asm/io.h #include asm/prom.h @@ -58,57 +59,8 @@ static void quirk_fsl_pcie_early(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; - - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = hose-first_busno; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } - - return 0; -} - -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); -} - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - #define MAX_PHYS_ADDR_BITS 40 static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; @@ -132,291 +84,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) -{ - resource_size_t pci_addr = res-start - offset; - resource_size_t phys_addr = res-start; - resource_size_t size = resource_size(res); - u32 flags = 0x80044000; /* enable mem R/W */ - unsigned int i; - - pr_debug(PCI MEM resource start 0x%016llx, size 0x%016llx.\n, - (u64)res-start, (u64)size); - - if (res-flags IORESOURCE_PREFETCH) - flags |= 0x1000; /* enable relaxed ordering */ - - for (i = 0; size 0; i++) { - unsigned int bits = min(ilog2(size), - __ffs(pci_addr | phys_addr)); - - if (index + i = 5) - return -1; - - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); - - pci_addr += (resource_size_t)1U bits; - phys_addr += (resource_size_t)1U bits; - size -= (resource_size_t)1U bits
[PATCH 05/12][v4] pci: fsl: port PCI ATMU related code
The patch ports PCI ATMU related code, just uses general IO API iowrite32be/ioread32be instead of out_be32/in_be32, uses structure fsl_pci instead of PowerPC's pci_controller and uses dev_*() instead of pr_*() to output the information. The patch also provides the weak function fsl_arch_pci64_dma_offset(), the architecture-specific driver may return different offset. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 190 -- include/linux/fsl/pci-common.h| 3 + 2 files changed, 103 insertions(+), 90 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index a706100..26ee4c3 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -35,6 +35,10 @@ #include sysdev/fsl_soc.h #include sysdev/fsl_pci.h +u64 __weak fsl_arch_pci64_dma_offset(void) +{ + return 0; +} int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) { @@ -225,8 +229,8 @@ static int early_fsl_find_capability(struct fsl_pci *pci, } static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) + unsigned int index, const struct resource *res, + resource_size_t offset) { resource_size_t pci_addr = res-start - offset; resource_size_t phys_addr = res-start; @@ -247,10 +251,10 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci, if (index + i = 5) return -1; - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); + iowrite32be(pci_addr 12, pci-pow[index + i].potar); + iowrite32be((u64)pci_addr 44, pci-pow[index + i].potear); + iowrite32be(phys_addr 12, pci-pow[index + i].powbar); + iowrite32be(flags | (bits - 1), pci-pow[index + i].powar); pci_addr += (resource_size_t)1U bits; phys_addr += (resource_size_t)1U bits; @@ -261,21 +265,19 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci, } /* atmu setup for fsl pci/pcie controller */ -static void setup_pci_atmu(struct pci_controller *hose) +static void setup_pci_atmu(struct fsl_pci *pci) { - struct ccsr_pci __iomem *pci = hose-private_data; int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; u64 mem, sz, paddr_hi = 0; u64 offset = 0, paddr_lo = ULLONG_MAX; u32 pcicsrbar = 0, pcicsrbar_sz; u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; - const char *name = hose-dn-full_name; const u64 *reg; int len; - if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { - if (in_be32(pci-block_rev1) = PCIE_IP_REV_2_2) { + if (pci-is_pcie) { + if (in_be32(pci-regs-block_rev1) = PCIE_IP_REV_2_2) { win_idx = 2; start_idx = 0; end_idx = 3; @@ -283,47 +285,54 @@ static void setup_pci_atmu(struct pci_controller *hose) } /* Disable all windows (except powar0 since it's ignored) */ - for(i = 1; i 5; i++) - out_be32(pci-pow[i].powar, 0); + for (i = 1; i 5; i++) + iowrite32be(0, pci-regs-pow[i].powar); for (i = start_idx; i end_idx; i++) - out_be32(pci-piw[i].piwar, 0); + iowrite32be(0, pci-regs-piw[i].piwar); /* Setup outbound MEM window */ - for(i = 0, j = 1; i 3; i++) { - if (!(hose-mem_resources[i].flags IORESOURCE_MEM)) + for (i = 0, j = 1; i 3; i++) { + if (!(pci-mem_resources[i].flags IORESOURCE_MEM)) continue; - paddr_lo = min(paddr_lo, (u64)hose-mem_resources[i].start); - paddr_hi = max(paddr_hi, (u64)hose-mem_resources[i].end); + paddr_lo = min_t(u64, paddr_lo, pci-mem_resources[i].start); + paddr_hi = max_t(u64, paddr_hi, pci-mem_resources[i].end); /* We assume all memory resources have the same offset */ - offset = hose-mem_offset[i]; - n = setup_one_atmu(pci, j, hose-mem_resources[i], offset); + offset = pci-mem_offset[i]; + n = setup_one_atmu(pci-regs, j, pci-mem_resources[i], + offset
[PATCH 07/12][v4] pci: fsl: port PCI platform driver
1. The patch ports FSL PCI platform driver. probe function initialize fsl_pci and register it to architecture PCI system, remove function removes fsl_pci from architecture PCI system. fsl_arch_pci_sys_register() and fsl_arch_pci_sys_remove() should be implemented in architecture-specific driver to provide register/remove functionality. 2. Remove architecture-specific header and unnecessary header. 3. Change Kconfig and Makefile to support FSL PCI common driver Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/Kconfig | 1 + drivers/pci/host/Kconfig | 10 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl-common.c | 43 +++ include/linux/fsl/pci-common.h| 6 ++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b44b52c..c708d80 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -694,6 +694,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL_COMMON if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 47d46c6..290afaa 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -33,4 +33,14 @@ config PCI_RCAR_GEN2 There are 3 internal PCI controllers available with a single built-in EHCI/OHCI host controller present on each one. +config PCI_FSL_COMMON + bool Common driver for Freescale PCI/PCIe controller + depends on FSL_SOC_BOOKE || PPC_86xx + help + This driver provides common support for PCI/PCIE controller + on Freescale embedded processors 85xx/86xx/QorIQ/Layerscape. + Additional drivers must be enabled in order to provide some + architecture-dependent functions and register the controller + to PCI subsystem. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 13fb333..1f8de80 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o +obj-$(CONFIG_PCI_FSL_COMMON) += pci-fsl-common.o diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 7184ac7..d608550 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -16,16 +16,12 @@ */ #include linux/kernel.h #include linux/pci.h -#include linux/delay.h -#include linux/string.h #include linux/init.h -#include linux/bootmem.h #include linux/memblock.h #include linux/log2.h -#include linux/slab.h -#include linux/uaccess.h #include linux/of_address.h #include linux/of_pci.h +#include linux/fsl/pci-common.h #include asm/io.h #include asm/prom.h @@ -665,12 +661,40 @@ static const struct of_device_id pci_ids[] = { static int fsl_pci_probe(struct platform_device *pdev) { int ret; - struct device_node *node; + struct fsl_pci *pci; - node = pdev-dev.of_node; - ret = fsl_add_bridge(pdev, fsl_pci_primary == node); + if (!of_device_is_available(pdev-dev.of_node)) { + dev_dbg(pdev-dev, disabled\n); + return -ENODEV; + } + + pci = devm_kzalloc(pdev-dev, sizeof(*pci), GFP_KERNEL); + if (!pci) { + dev_err(pdev-dev, no memory for fsl_pci\n); + return -ENOMEM; + } + + ret = fsl_pci_setup(pdev, pci); + if (ret) + return ret; + + ret = fsl_arch_pci_sys_register(pci); + if (ret) { + dev_err(pdev-dev, failed to register pcie to Arch\n); + return ret; + } + + return 0; +} + +static int fsl_pci_remove(struct platform_device *pdev) +{ + struct fsl_pci *pci = platform_get_drvdata(pdev); + + if (!pci) + return -ENODEV; - mpc85xx_pci_err_probe(pdev); + fsl_arch_pci_sys_remove(pci); return 0; } @@ -714,6 +738,7 @@ static struct platform_driver fsl_pci_driver = { .of_match_table = pci_ids, }, .probe = fsl_pci_probe, + .remove = fsl_pci_remove, }; static int __init fsl_pci_init(void) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 02bcf5b..8d33354 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -166,5 +166,11 @@ extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr); /* Return PCI64 DMA offset */ u64 fsl_arch_pci64_dma_offset(void); +/* Register PCI/PCIe controller to architecture system */ +extern
[PATCH 08/12][v4] pci: fsl: add PowerPC PCI driver
1. Implement fsl_arch_pci64_dma_offset() to return PowerPC PCI64 DMA offset 2. Implement fsl_arch_sys_to_pci() to convert pci_controller to fsl_pci 3. Implement fsl_arch_fake_pci_bus() to fake pci_controller and PCI bus. 4. Implement fsl_arch_pci_exclude_device() to call ppc_md.pci_exclude_device() 5. Implement fsl_arch_pci_sys_register() to initialize pci_controller according to fsl_pci, add register PCI controller to PowerPC PCI subsystem. 6. Implement fsl_arch_pci_sys_remove() to remove PCI controller from PowerPC PCI subsystem. 7. Add mpc83xx_pcie_check_link() because pci-fsl-common dose not support mpc83xx. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 142 +++--- 1 file changed, 135 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 0764385..38e8dca 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_early(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose-private_data; + + /* Update the first bus number */ + if (pci-first_busno != hose-first_busno) + pci-first_busno = hose-first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = hose; + hose.private_data = pci; + bus.ops = pci-ops; + + return bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + bool is_pcie, no_link; + int i; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose-indirect_type PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci-is_pcie; + no_link = !fsl_pci_check_link(pci); if (bus-parent == hose-bus (is_pcie || no_link)) { for (i = 0; i PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci-sys; + + if (!hose) + return PCIBIOS_SUCCESSFUL; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(hose, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +int fsl_arch_pci_sys_register(struct fsl_pci *pci) +{ + struct pci_controller *hose; + + pci_add_flags(PCI_REASSIGN_ALL_BUS); + hose = pcibios_alloc_controller(pci-dn); + if (!hose) + return -ENOMEM; + + /* set platform device as the parent */ + hose-private_data = pci; + hose-parent = pci-dev; + hose-first_busno = pci-first_busno; + hose-last_busno = pci-last_busno; + hose-ops = pci-ops; + +#ifdef CONFIG_PPC32 + /* On 32 bits, limit I/O space to 16MB */ + if (pci-pci_io_size 0x0100) + pci-pci_io_size = 0x0100; + + /* 32 bits needs to map IOs here */ + hose-io_base_virt = ioremap(pci-io_base_phys + pci-io_resource.start, +pci-pci_io_size); + + /* Expect trouble if pci_addr is not 0 */ + if (fsl_pci_primary == pci-dn) + isa_io_base = (unsigned long)hose-io_base_virt; +#endif /* CONFIG_PPC32 */ + + hose-pci_io_size = pci-io_resource.start + pci-pci_io_size
[PATCH 06/12][v4] pci: fsl: port PCI controller setup code
PCI controller setup code will initialize structure fsl_pci according to PCI dts node and initialize PCI command register and ATMU. The patch uses general API of_pci_parse_bus_range to parse PCI bus range, uses general of_address's API to parse PCI IO/MEM ranges. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 179 +- 1 file changed, 97 insertions(+), 82 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 26ee4c3..7184ac7 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -24,6 +24,8 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/of_address.h +#include linux/of_pci.h #include asm/io.h #include asm/prom.h @@ -498,131 +500,144 @@ static void setup_pci_atmu(struct fsl_pci *pci) } } -static void __init setup_pci_cmd(struct pci_controller *hose) +static void __init setup_pci_cmd(struct fsl_pci *pci) { u16 cmd; int cap_x; - early_read_config_word(hose, 0, 0, PCI_COMMAND, cmd); + early_fsl_read_config_word(pci, 0, 0, PCI_COMMAND, cmd); cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + early_fsl_write_config_word(pci, 0, 0, PCI_COMMAND, cmd); - cap_x = early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX); + cap_x = early_fsl_find_capability(pci, 0, 0, PCI_CAP_ID_PCIX); if (cap_x) { int pci_x_cmd = cap_x + PCI_X_CMD; cmd = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E; - early_write_config_word(hose, 0, 0, pci_x_cmd, cmd); - } else { - early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); - } + early_fsl_write_config_word(pci, 0, 0, pci_x_cmd, cmd); + } else + early_fsl_write_config_byte(pci, 0, 0, PCI_LATENCY_TIMER, + 0x80); } -int __init fsl_add_bridge(struct platform_device *pdev, int is_primary) +static int __init +fsl_pci_setup(struct platform_device *pdev, struct fsl_pci *pci) { - int len; - struct pci_controller *hose; - struct resource rsrc; - const int *bus_range; + struct resource *rsrc; u8 hdr_type, progif; - struct device_node *dev; - struct ccsr_pci __iomem *pci; - - dev = pdev-dev.of_node; + struct device_node *dn; + struct of_pci_range range; + struct of_pci_range_parser parser; + int mem = 0; - if (!of_device_is_available(dev)) { - pr_warning(%s: disabled\n, dev-full_name); - return -ENODEV; - } + dn = pdev-dev.of_node; + pci-dn = dn; + pci-dev = pdev-dev; - pr_debug(Adding PCI host bridge %s\n, dev-full_name); + dev_info(pdev-dev, Find controller %s\n, dn-full_name); /* Fetch host bridge registers address */ - if (of_address_to_resource(dev, 0, rsrc)) { - printk(KERN_WARNING Can't get pci register base!); - return -ENOMEM; + rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rsrc) { + dev_err(pdev-dev, Can't get pci register base!); + return -EINVAL; } + dev_info(pdev-dev, REG 0x%016llx..0x%016llx\n, +(u64)rsrc-start, (u64)rsrc-end); - /* Get bus range if any */ - bus_range = of_get_property(dev, bus-range, len); - if (bus_range == NULL || len 2 * sizeof(int)) - printk(KERN_WARNING Can't get bus-range for %s, assume -bus 0\n, dev-full_name); - - pci_add_flags(PCI_REASSIGN_ALL_BUS); - hose = pcibios_alloc_controller(dev); - if (!hose) - return -ENOMEM; + /* Parse pci range resources from device tree */ + if (of_pci_range_parser_init(parser, dn)) { + dev_err(pdev-dev, missing ranges property\n); + return -EINVAL; + } - /* set platform device as the parent */ - hose-parent = pdev-dev; - hose-first_busno = bus_range ? bus_range[0] : 0x0; - hose-last_busno = bus_range ? bus_range[1] : 0xff; + /* Get the I/O and memory ranges from device tree */ + for_each_of_pci_range(parser, range) { + unsigned long restype = range.flags IORESOURCE_TYPE_BITS; + if (restype == IORESOURCE_IO) { + of_pci_range_to_resource(range, dn, +pci-io_resource
[PATCH 11/12][v4] pci: fsl: update PCI EDAC driver
1. The pci-fsl-common driver has set fsl_pci to device as drvdata, so EDAC driver can not call dev_set_drvdata() again. fsl_pci contains regs field to point PCI CCSR, so EDAC may directly use the pointer and not need to call devm_ioremap(). 2. Add mpc85xx_pci_err_remove() to disable PCI error interrupt and delete PCI EDAC from EDAC subsystem. 3. AER uses the same IRQ, so change IRQ handling mode as shared to avoid AER can not request IRQ. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: Changed IRQ handling mode as shared to avoid aer can not request IRQ. v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Added mpc85xx_pci_err_remove() Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.h | 6 + drivers/edac/mpc85xx_edac.c | 61 +-- drivers/edac/mpc85xx_edac.h | 1 + 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 6d9bec4..2e3455e 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -236,6 +236,7 @@ void fsl_arch_pci_sys_remove(struct fsl_pci *pci) if (!hose) return; + mpc85xx_pci_err_remove(to_platform_device(pci-dev)); pcibios_free_controller(hose); } diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index ce77aad..ae4dbe2 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -35,11 +35,17 @@ static inline void fsl_pci_assign_primary(void) {} #ifdef CONFIG_EDAC_MPC85XX int mpc85xx_pci_err_probe(struct platform_device *op); +int mpc85xx_pci_err_remove(struct platform_device *op); #else static inline int mpc85xx_pci_err_probe(struct platform_device *op) { return -ENOTSUPP; } +static inline int mpc85xx_pci_err_remove(struct platform_device *op) +{ + return -ENOTSUPP; +} + #endif #ifdef CONFIG_FSL_PCI diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index fd46b0b..ea37db9 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -21,6 +21,7 @@ #include linux/of_platform.h #include linux/of_device.h +#include linux/fsl/pci-common.h #include edac_module.h #include edac_core.h #include mpc85xx_edac.h @@ -214,11 +215,13 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) int mpc85xx_pci_err_probe(struct platform_device *op) { + struct fsl_pci *fslpci; struct edac_pci_ctl_info *pci; struct mpc85xx_pci_pdata *pdata; - struct resource r; int res = 0; + fslpci = platform_get_drvdata(op); + if (!devres_open_group(op-dev, mpc85xx_pci_err_probe, GFP_KERNEL)) return -ENOMEM; @@ -239,7 +242,6 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata = pci-pvt_info; pdata-name = mpc85xx_pci_err; pdata-irq = NO_IRQ; - dev_set_drvdata(op-dev, pci); pci-dev = op-dev; pci-mod_name = EDAC_MOD_STR; pci-ctl_name = pdata-name; @@ -250,30 +252,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata-edac_idx = edac_pci_idx++; - res = of_address_to_resource(op-dev.of_node, 0, r); - if (res) { - printk(KERN_ERR %s: Unable to get resource for - PCI err regs\n, __func__); - goto err; - } - /* we only need the error registers */ - r.start += 0xe00; - - if (!devm_request_mem_region(op-dev, r.start, resource_size(r), - pdata-name)) { - printk(KERN_ERR %s: Error while requesting mem region\n, - __func__); - res = -EBUSY; - goto err; - } - - pdata-pci_vbase = devm_ioremap(op-dev, r.start, resource_size(r)); - if (!pdata-pci_vbase) { - printk(KERN_ERR %s: Unable to setup PCI err regs\n, __func__); - res = -ENOMEM; - goto err; - } + pdata-pci_vbase = (void *)fslpci-regs + MPC85XX_PCI_ERR_OFFSET; orig_pci_err_cap_dr = in_be32(pdata-pci_vbase + MPC85XX_PCI_ERR_CAP_DR); @@ -297,7 +277,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op) if (edac_op_state == EDAC_OPSTATE_INT) { pdata-irq = irq_of_parse_and_map(op-dev.of_node, 0); res = devm_request_irq(op-dev, pdata-irq, - mpc85xx_pci_isr, IRQF_DISABLED, + mpc85xx_pci_isr, + IRQF_DISABLED | IRQF_SHARED, [EDAC] PCI err, pci); if (res 0) { printk(KERN_ERR @@ -327,6 +308,34 @@ err: } EXPORT_SYMBOL(mpc85xx_pci_err_probe); +int mpc85xx_pci_err_remove(struct
[PATCH 12/12][v4] pci: fsl: fix function check_pci_ctl_endpt_part
The new FSL PCI driver does not use cfg_addr of pci_controller, we may directly access PCI CCSR using fsl_pci-regs. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: The new patch to fix function check_pci_ctl_endpt_part Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.h | 5 - drivers/iommu/fsl_pamu_domain.c | 6 -- include/linux/fsl/pci-common.h | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index ae4dbe2..3176eb2 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -16,11 +16,6 @@ struct platform_device; - -/* FSL PCI controller BRR1 register */ -#define PCI_FSL_BRR1 0xbf8 -#define PCI_FSL_BRR1_VER 0x - extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); extern int mpc83xx_add_bridge(struct device_node *dev); u64 fsl_pci_immrbar_base(struct pci_controller *hose); diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index c857c30..dd7bc25 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -36,6 +36,7 @@ #include asm/pci-bridge.h #include sysdev/fsl_pci.h +#include linux/fsl/pci-common.h #include fsl_pamu_domain.h #include pci.h @@ -908,10 +909,11 @@ static struct iommu_group *get_device_iommu_group(struct device *dev) static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) { u32 version; + struct fsl_pci *pci = fsl_arch_sys_to_pci(pci_ctl); /* Check the PCI controller version number by readding BRR1 register */ - version = in_be32(pci_ctl-cfg_addr + (PCI_FSL_BRR1 2)); - version = PCI_FSL_BRR1_VER; + version = in_be32(pci-regs-block_rev1); + version = PCIE_IP_REV_MASK; /* If PCI controller version is = 0x204 we can partition endpoints*/ if (version = 0x204) return 1; diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 3247682..4e4191e 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -18,6 +18,7 @@ #define PCIE_LTSSM_L0 0x16/* L0 state */ #define PCIE_IP_REV_2_20x02080202 /* PCIE IP block version Rev2.2 */ #define PCIE_IP_REV_3_00x02080300 /* PCIE IP block version Rev3.0 */ +#define PCIE_IP_REV_MASK 0x #define PIWAR_EN 0x8000 /* Enable */ #define PIWAR_PF 0x2000 /* prefetch */ #define PIWAR_TGI_LOCAL0x00f0 /* target - local memory */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 09/12][v4] pci: fsl: update PCI PM driver
The patch updates PCI PM driver, uses fsl_pci instead of pci_controller. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 13 +++-- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index d608550..e3696eb 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -702,19 +702,12 @@ static int fsl_pci_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int fsl_pci_resume(struct device *dev) { - struct pci_controller *hose; - struct resource pci_rsrc; + struct fsl_pci *pci = dev_get_drvdata(dev); - hose = pci_find_hose_for_OF_device(dev-of_node); - if (!hose) + if (!pci) return -ENODEV; - if (of_address_to_resource(dev-of_node, 0, pci_rsrc)) { - dev_err(dev, Get pci register base failed.); - return -ENODEV; - } - - setup_pci_atmu(hose); + setup_pci_atmu(pci); return 0; } -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 10/12][v4] pci: fsl: support function fsl_pci_assign_primary
Change pci_ids to fsl_pci_ids Freescale-specific name and change static to extern modifier for using in fsl_pci_assign_primary(). Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 5 +++-- drivers/pci/host/pci-fsl-common.c | 4 ++-- include/linux/fsl/pci-common.h| 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 38e8dca..6d9bec4 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -736,7 +736,8 @@ void fsl_pci_assign_primary(void) of_node_put(np); np = fsl_pci_primary; - if (of_match_node(pci_ids, np) of_device_is_available(np)) + if (of_match_node(fsl_pci_ids, np) + of_device_is_available(np)) return; } @@ -745,7 +746,7 @@ void fsl_pci_assign_primary(void) * designate one as primary. This can go away once * various bugs with primary-less systems are fixed. */ - for_each_matching_node(np, pci_ids) { + for_each_matching_node(np, fsl_pci_ids) { if (of_device_is_available(np)) { fsl_pci_primary = np; of_node_put(np); diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index e3696eb..0be7bc0 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -637,7 +637,7 @@ no_bridge: return -ENODEV; } -static const struct of_device_id pci_ids[] = { +const struct of_device_id fsl_pci_ids[] = { { .compatible = fsl,mpc8540-pci, }, { .compatible = fsl,mpc8548-pcie, }, { .compatible = fsl,mpc8610-pci, }, @@ -728,7 +728,7 @@ static struct platform_driver fsl_pci_driver = { .driver = { .name = fsl-pci, .pm = PCI_PM_OPS, - .of_match_table = pci_ids, + .of_match_table = fsl_pci_ids, }, .probe = fsl_pci_probe, .remove = fsl_pci_remove, diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 8d33354..3247682 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -143,6 +143,8 @@ struct fsl_pci { void *sys; }; +extern const struct of_device_id fsl_pci_ids[]; + /* * Convert architecture specific pci controller structure to fsl_pci * PowerPC uses structure pci_controller and ARM uses structure pci_sys_data -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 02/12][v3] pci: fsl: add structure fsl_pci
PowerPC uses structure pci_controller to describe PCI controller, but ARM uses structure pci_sys_data. In order to support PowerPC and ARM simultaneously, the patch adds a structure fsl_pci that contains most of the members of the pci_controller and pci_sys_data. Meanwhile, it defines a interface fsl_arch_sys_to_pci() which should be implemented in architecture-specific PCI controller driver to convert pci_controller or pci_sys_data to fsl_pci. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ include/linux/fsl/pci-common.h | 41 + 1 file changed, 41 insertions(+) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 5e4f683..e56a040 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -102,5 +102,46 @@ struct ccsr_pci { }; +/* + * Structure of a PCI controller (host bridge) + */ +struct fsl_pci { + struct list_head node; + bool is_pcie; + struct device_node *dn; + struct device *dev; + + int first_busno; + int last_busno; + int self_busno; + struct resource busn; + + struct pci_ops *ops; + struct ccsr_pci __iomem *regs; + + u32 indirect_type; + + struct resource io_resource; + resource_size_t io_base_phys; + resource_size_t pci_io_size; + + struct resource mem_resources[3]; + resource_size_t mem_offset[3]; + + int global_number; /* PCI domain number */ + + resource_size_t dma_window_base_cur; + resource_size_t dma_window_size; + + void *sys; +}; + +/* + * Convert architecture specific pci controller structure to fsl_pci + * PowerPC uses structure pci_controller and ARM uses structure pci_sys_data + * to describe pci controller. + */ +extern struct fsl_pci *fsl_arch_sys_to_pci(void *sys); + #endif /* __PCI_COMMON_H */ #endif /* __KERNEL__ */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 01/12][v3] pci: fsl: derive the common PCI driver to drivers/pci/host
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pci-fsl-common.c and leaves the architecture specific functions which should be implemented in arch related files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v2-v3: no change v1-v2: 1. rename pci.h to pci-common.h 2. rename pci-fsl.c to pci-fsl-common.c Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 521 +- arch/powerpc/sysdev/fsl_pci.h | 89 .../fsl_pci.c = drivers/pci/host/pci-fsl-common.c | 591 + .../fsl_pci.h = include/linux/fsl/pci-common.h| 45 +- 4 files changed, 7 insertions(+), 1239 deletions(-) copy arch/powerpc/sysdev/fsl_pci.c = drivers/pci/host/pci-fsl-common.c (54%) copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci-common.h (79%) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ccfb50d..26039e3 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -27,6 +27,7 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/fsl/pci-common.h #include asm/io.h #include asm/prom.h @@ -58,57 +59,8 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; - - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = hose-first_busno; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } - - return 0; -} - -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); -} - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - #define MAX_PHYS_ADDR_BITS 40 static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; @@ -132,291 +84,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) -{ - resource_size_t pci_addr = res-start - offset; - resource_size_t phys_addr = res-start; - resource_size_t size = resource_size(res); - u32 flags = 0x80044000; /* enable mem R/W */ - unsigned int i; - - pr_debug(PCI MEM resource start 0x%016llx, size 0x%016llx.\n, - (u64)res-start, (u64)size); - - if (res-flags IORESOURCE_PREFETCH) - flags |= 0x1000; /* enable relaxed ordering */ - - for (i = 0; size 0; i++) { - unsigned int bits = min(ilog2(size), - __ffs(pci_addr | phys_addr)); - - if (index + i = 5) - return -1; - - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); - - pci_addr += (resource_size_t)1U bits; - phys_addr += (resource_size_t)1U bits; - size -= (resource_size_t)1U bits
[PATCH 04/12][v3] pci: fsl: add early PCI indirect access support
The driver needs to read/write PCI configuration very early, at that time architecture-specific PCI controller structure and PCI bus have not been created. The patch provides an interface fsl_arch_fake_pci_bus which should be implemented in architecture-specific PCI driver to fake a PCI controller structure and PCI bus. Using the fake PCI controller and PCI bus, the patch provides the early indirect read/write functions. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 26 ++ include/linux/fsl/pci-common.h| 7 +++ 2 files changed, 33 insertions(+) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 8bc9a64..505a6a1 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -204,6 +204,32 @@ static struct pci_ops fsl_indirect_pci_ops = { .write = fsl_indirect_write_config, }; +#define EARLY_FSL_PCI_OP(rw, size, type) \ +int early_fsl_##rw##_config_##size(struct fsl_pci *pci, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_bus_##rw##_config_##size(fsl_arch_fake_pci_bus(pci, bus),\ + devfn, offset, value); \ +} + +EARLY_FSL_PCI_OP(read, byte, u8 *) +EARLY_FSL_PCI_OP(read, word, u16 *) +EARLY_FSL_PCI_OP(read, dword, u32 *) +EARLY_FSL_PCI_OP(write, byte, u8) +EARLY_FSL_PCI_OP(write, word, u16) +EARLY_FSL_PCI_OP(write, dword, u32) + +static int early_fsl_find_capability(struct fsl_pci *pci, +int busnr, int devfn, int cap) +{ + struct pci_bus *bus = fsl_arch_fake_pci_bus(pci, busnr); + + if (!bus) + return 0; + + return pci_bus_find_capability(bus, devfn, cap); +} + static int setup_one_atmu(struct ccsr_pci __iomem *pci, unsigned int index, const struct resource *res, resource_size_t offset) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 7df4355..a3aca29 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -149,5 +149,12 @@ bool fsl_pci_check_link(struct fsl_pci *pci); /* To avoid touching specified devices */ int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn); +/* + * To fake a PCI bus + * it is called by early_fsl_*(), at that time the architecture-dependent + * pci controller and pci bus have not been created. + */ +extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr); + #endif /* __PCI_COMMON_H */ #endif /* __KERNEL__ */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 05/12][v3] pci: fsl: port PCI ATMU related code
The patch ports PCI ATMU related code, just uses general IO API iowrite32be/ioread32be instead of out_be32/in_be32, uses structure fsl_pci instead of PowerPC's pci_controller and uses dev_*() instead of pr_*() to output the information. The patch also provides the weak function fsl_arch_pci64_dma_offset(), the architecture-specific driver may return different offset. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 191 -- include/linux/fsl/pci-common.h| 3 + 2 files changed, 104 insertions(+), 90 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 505a6a1..f15b605 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -42,6 +42,11 @@ #define INDIRECT_TYPE_BIG_ENDIAN 0x0010 #define INDIRECT_TYPE_FSL_CFG_REG_LINK 0x0040 +u64 __weak fsl_arch_pci64_dma_offset(void) +{ + return 0; +} + int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) { return PCIBIOS_SUCCESSFUL; @@ -231,8 +236,8 @@ static int early_fsl_find_capability(struct fsl_pci *pci, } static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) + unsigned int index, const struct resource *res, + resource_size_t offset) { resource_size_t pci_addr = res-start - offset; resource_size_t phys_addr = res-start; @@ -253,10 +258,10 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci, if (index + i = 5) return -1; - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); + iowrite32be(pci_addr 12, pci-pow[index + i].potar); + iowrite32be((u64)pci_addr 44, pci-pow[index + i].potear); + iowrite32be(phys_addr 12, pci-pow[index + i].powbar); + iowrite32be(flags | (bits - 1), pci-pow[index + i].powar); pci_addr += (resource_size_t)1U bits; phys_addr += (resource_size_t)1U bits; @@ -267,21 +272,19 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci, } /* atmu setup for fsl pci/pcie controller */ -static void setup_pci_atmu(struct pci_controller *hose) +static void setup_pci_atmu(struct fsl_pci *pci) { - struct ccsr_pci __iomem *pci = hose-private_data; int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; u64 mem, sz, paddr_hi = 0; u64 offset = 0, paddr_lo = ULLONG_MAX; u32 pcicsrbar = 0, pcicsrbar_sz; u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; - const char *name = hose-dn-full_name; const u64 *reg; int len; - if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { - if (in_be32(pci-block_rev1) = PCIE_IP_REV_2_2) { + if (pci-is_pcie) { + if (in_be32(pci-regs-block_rev1) = PCIE_IP_REV_2_2) { win_idx = 2; start_idx = 0; end_idx = 3; @@ -289,47 +292,54 @@ static void setup_pci_atmu(struct pci_controller *hose) } /* Disable all windows (except powar0 since it's ignored) */ - for(i = 1; i 5; i++) - out_be32(pci-pow[i].powar, 0); + for (i = 1; i 5; i++) + iowrite32be(0, pci-regs-pow[i].powar); for (i = start_idx; i end_idx; i++) - out_be32(pci-piw[i].piwar, 0); + iowrite32be(0, pci-regs-piw[i].piwar); /* Setup outbound MEM window */ - for(i = 0, j = 1; i 3; i++) { - if (!(hose-mem_resources[i].flags IORESOURCE_MEM)) + for (i = 0, j = 1; i 3; i++) { + if (!(pci-mem_resources[i].flags IORESOURCE_MEM)) continue; - paddr_lo = min(paddr_lo, (u64)hose-mem_resources[i].start); - paddr_hi = max(paddr_hi, (u64)hose-mem_resources[i].end); + paddr_lo = min_t(u64, paddr_lo, pci-mem_resources[i].start); + paddr_hi = max_t(u64, paddr_hi, pci-mem_resources[i].end); /* We assume all memory resources have the same offset */ - offset = hose-mem_offset[i]; - n = setup_one_atmu(pci, j, hose-mem_resources[i], offset); + offset = pci-mem_offset[i]; + n = setup_one_atmu(pci-regs, j
[PATCH 03/12][v3] pci: fsl: add PCI indirect access support
The patch adds PCI indirect read/write functions. The main code is ported from arch/powerpc/sysdev/indirect_pci.c. We use general IO API iowrite32be/ioread32be instead of out_be32/in_be32, and use structure fsl_Pci instead of PowerPC's pci_controller. The patch also provides fsl_pcie_check_link() to check PCI link. The weak function fsl_arch_pci_exclude_device() is provided to call ppc_md.pci_exclude_device() for PowerPC architecture. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 169 -- include/linux/fsl/pci-common.h| 6 ++ 2 files changed, 151 insertions(+), 24 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 69d338b..8bc9a64 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -35,52 +35,173 @@ #include sysdev/fsl_soc.h #include sysdev/fsl_pci.h -static int fsl_pcie_check_link(struct pci_controller *hose) +/* Indirect type */ +#define INDIRECT_TYPE_EXT_REG 0x0002 +#define INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x0004 +#define INDIRECT_TYPE_NO_PCIE_LINK 0x0008 +#define INDIRECT_TYPE_BIG_ENDIAN 0x0010 +#define INDIRECT_TYPE_FSL_CFG_REG_LINK 0x0040 + +int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + return PCIBIOS_SUCCESSFUL; +} + +static int fsl_pci_read_config(struct fsl_pci *pci, int bus, int devfn, + int offset, int len, u32 *val) +{ + u32 bus_no, reg, data; + + if (pci-indirect_type INDIRECT_TYPE_NO_PCIE_LINK) { + if (bus != pci-first_busno) + return PCIBIOS_DEVICE_NOT_FOUND; + if (devfn != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (fsl_arch_pci_exclude_device(pci, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + bus_no = (bus == pci-first_busno) ? pci-self_busno : bus; + + if (pci-indirect_type INDIRECT_TYPE_EXT_REG) + reg = ((offset 0xf00) 16) | (offset 0xfc); + else + reg = offset 0xfc; + + if (pci-indirect_type INDIRECT_TYPE_BIG_ENDIAN) + iowrite32be(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + else + iowrite32(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + + /* +* Note: the caller has already checked that offset is +* suitably aligned and that len is 1, 2 or 4. +*/ + data = ioread32(pci-regs-config_data); + switch (len) { + case 1: + *val = (data (8 * (offset 3))) 0xff; + break; + case 2: + *val = (data (8 * (offset 3))) 0x; + break; + default: + *val = data; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int fsl_pci_write_config(struct fsl_pci *pci, int bus, int devfn, +int offset, int len, u32 val) +{ + void __iomem *cfg_data; + u32 bus_no, reg; + + if (pci-indirect_type INDIRECT_TYPE_NO_PCIE_LINK) { + if (bus != pci-first_busno) + return PCIBIOS_DEVICE_NOT_FOUND; + if (devfn != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (fsl_arch_pci_exclude_device(pci, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + bus_no = (bus == pci-first_busno) ? + pci-self_busno : bus; + + if (pci-indirect_type INDIRECT_TYPE_EXT_REG) + reg = ((offset 0xf00) 16) | (offset 0xfc); + else + reg = offset 0xfc; + + if (pci-indirect_type INDIRECT_TYPE_BIG_ENDIAN) + iowrite32be(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + else + iowrite32(0x8000 | (bus_no 16) | (devfn 8) | reg, + pci-regs-config_addr); + + /* suppress setting of PCI_PRIMARY_BUS */ + if (pci-indirect_type INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) + if ((offset == PCI_PRIMARY_BUS) + (bus == pci-first_busno)) + val = 0xff00; + + /* +* Note: the caller has already checked that offset is +* suitably aligned and that len is 1, 2 or 4. +*/ + cfg_data = ((void *) (pci-regs-config_data)) + (offset 3); + switch (len) { + case 1: + iowrite8(val, cfg_data); + break; + case 2
[PATCH 09/12][v3] pci: fsl: update PCI PM driver
The patch updates PCI PM driver, uses fsl_pci instead of pci_controller. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 13 +++-- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index c7bc472..729a5f4 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -699,19 +699,12 @@ static int fsl_pci_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int fsl_pci_resume(struct device *dev) { - struct pci_controller *hose; - struct resource pci_rsrc; + struct fsl_pci *pci = dev_get_drvdata(dev); - hose = pci_find_hose_for_OF_device(dev-of_node); - if (!hose) + if (!pci) return -ENODEV; - if (of_address_to_resource(dev-of_node, 0, pci_rsrc)) { - dev_err(dev, Get pci register base failed.); - return -ENODEV; - } - - setup_pci_atmu(hose); + setup_pci_atmu(pci); return 0; } -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 07/12][v3] pci: fsl: port PCI platform driver
1. The patch ports FSL PCI platform driver. probe function initialize fsl_pci and register it to architecture PCI system, remove function removes fsl_pci from architecture PCI system. fsl_arch_pci_sys_register() and fsl_arch_pci_sys_remove() should be implemented in architecture-specific driver to provide register/remove functionality. 2. Remove architecture-specific header and unnecessary header. 3. Change Kconfig and Makefile to support FSL PCI common driver Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/Kconfig | 1 + drivers/pci/host/Kconfig | 10 drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl-common.c | 53 +-- include/linux/fsl/pci-common.h| 6 + 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 38f3b7e..7447d97d 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -690,6 +690,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL_COMMON if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3d95048..48242b33 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -19,4 +19,14 @@ config PCI_TEGRA bool NVIDIA Tegra PCIe controller depends on ARCH_TEGRA +config PCI_FSL_COMMON + bool Common driver for Freescale PCI/PCIe controller + depends on FSL_SOC_BOOKE || PPC_86xx + help + This driver provides common support for PCI/PCIE controller + on Freescale embedded processors 85xx/86xx/QorIQ/Layerscape. + Additional drivers must be enabled in order to provide some + architecture-dependent functions and register the controller + to PCI subsystem. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index c9a997b..7c338a7 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o +obj-$(CONFIG_PCI_FSL_COMMON) += pci-fsl-common.o diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index e09a0ec..c7bc472 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -16,26 +16,12 @@ */ #include linux/kernel.h #include linux/pci.h -#include linux/delay.h -#include linux/string.h #include linux/init.h -#include linux/bootmem.h #include linux/memblock.h #include linux/log2.h -#include linux/slab.h -#include linux/uaccess.h #include linux/of_address.h #include linux/of_pci.h - -#include asm/io.h -#include asm/prom.h -#include asm/pci-bridge.h -#include asm/ppc-pci.h -#include asm/machdep.h -#include asm/disassemble.h -#include asm/ppc-opcode.h -#include sysdev/fsl_soc.h -#include sysdev/fsl_pci.h +#include linux/fsl/pci-common.h /* Indirect type */ #define INDIRECT_TYPE_EXT_REG 0x0002 @@ -672,12 +658,40 @@ static const struct of_device_id pci_ids[] = { static int fsl_pci_probe(struct platform_device *pdev) { int ret; - struct device_node *node; + struct fsl_pci *pci; + + if (!of_device_is_available(pdev-dev.of_node)) { + dev_dbg(pdev-dev, disabled\n); + return -ENODEV; + } + + pci = devm_kzalloc(pdev-dev, sizeof(*pci), GFP_KERNEL); + if (!pci) { + dev_err(pdev-dev, no memory for fsl_pci\n); + return -ENOMEM; + } + + ret = fsl_pci_setup(pdev, pci); + if (ret) + return ret; + + ret = fsl_arch_pci_sys_register(pci); + if (ret) { + dev_err(pdev-dev, failed to register pcie to Arch\n); + return ret; + } + + return 0; +} - node = pdev-dev.of_node; - ret = fsl_add_bridge(pdev, fsl_pci_primary == node); +static int fsl_pci_remove(struct platform_device *pdev) +{ + struct fsl_pci *pci = platform_get_drvdata(pdev); + + if (!pci) + return -ENODEV; - mpc85xx_pci_err_probe(pdev); + fsl_arch_pci_sys_remove(pci); return 0; } @@ -721,6 +735,7 @@ static struct platform_driver fsl_pci_driver = { .of_match_table = pci_ids, }, .probe = fsl_pci_probe, + .remove = fsl_pci_remove, }; static int __init fsl_pci_init(void) diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 490ee53..bfb1f03 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -159,5 +159,11 @@ extern struct pci_bus
[PATCH 10/12][v3] pci: fsl: support function fsl_pci_assign_primary
Change pci_ids to fsl_pci_ids Freescale-specific name and change static to extern modifier for using in fsl_pci_assign_primary(). Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 5 +++-- drivers/pci/host/pci-fsl-common.c | 4 ++-- include/linux/fsl/pci-common.h| 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 0a0c240..40d2e1d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -735,7 +735,8 @@ void fsl_pci_assign_primary(void) of_node_put(np); np = fsl_pci_primary; - if (of_match_node(pci_ids, np) of_device_is_available(np)) + if (of_match_node(fsl_pci_ids, np) + of_device_is_available(np)) return; } @@ -744,7 +745,7 @@ void fsl_pci_assign_primary(void) * designate one as primary. This can go away once * various bugs with primary-less systems are fixed. */ - for_each_matching_node(np, pci_ids) { + for_each_matching_node(np, fsl_pci_ids) { if (of_device_is_available(np)) { fsl_pci_primary = np; of_node_put(np); diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index 729a5f4..8b4f793 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -634,7 +634,7 @@ no_bridge: return -ENODEV; } -static const struct of_device_id pci_ids[] = { +const struct of_device_id fsl_pci_ids[] = { { .compatible = fsl,mpc8540-pci, }, { .compatible = fsl,mpc8548-pcie, }, { .compatible = fsl,mpc8610-pci, }, @@ -725,7 +725,7 @@ static struct platform_driver fsl_pci_driver = { .driver = { .name = fsl-pci, .pm = PCI_PM_OPS, - .of_match_table = pci_ids, + .of_match_table = fsl_pci_ids, }, .probe = fsl_pci_probe, .remove = fsl_pci_remove, diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index bfb1f03..84b0801 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -136,6 +136,8 @@ struct fsl_pci { void *sys; }; +extern const struct of_device_id fsl_pci_ids[]; + /* * Convert architecture specific pci controller structure to fsl_pci * PowerPC uses structure pci_controller and ARM uses structure pci_sys_data -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 08/12][v3] pci: fsl: add PowerPC PCI driver
1. Implement fsl_arch_pci64_dma_offset() to return PowerPC PCI64 DMA offset 2. Implement fsl_arch_sys_to_pci() to convert pci_controller to fsl_pci 3. Implement fsl_arch_fake_pci_bus() to fake pci_controller and PCI bus. 4. Implement fsl_arch_pci_exclude_device() to call ppc_md.pci_exclude_device() 5. Implement fsl_arch_pci_sys_register() to initialize pci_controller according to fsl_pci, add register PCI controller to PowerPC PCI subsystem. 6. Implement fsl_arch_pci_sys_remove() to remove PCI controller from PowerPC PCI subsystem. 7. Add mpc83xx_pcie_check_link() because pci-fsl-common dose not support mpc83xx. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 142 +++--- 1 file changed, 135 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 26039e3..0a0c240 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose-private_data; + + /* Update the first bus number */ + if (pci-first_busno != hose-first_busno) + pci-first_busno = hose-first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = hose; + hose.private_data = pci; + bus.ops = pci-ops; + + return bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + bool is_pcie, no_link; + int i; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose-indirect_type PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci-is_pcie; + no_link = !fsl_pci_check_link(pci); if (bus-parent == hose-bus (is_pcie || no_link)) { for (i = 0; i PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci-sys; + + if (!hose) + return PCIBIOS_SUCCESSFUL; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(hose, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +int fsl_arch_pci_sys_register(struct fsl_pci *pci) +{ + struct pci_controller *hose; + + pci_add_flags(PCI_REASSIGN_ALL_BUS); + hose = pcibios_alloc_controller(pci-dn); + if (!hose) + return -ENOMEM; + + /* set platform device as the parent */ + hose-private_data = pci; + hose-parent = pci-dev; + hose-first_busno = pci-first_busno; + hose-last_busno = pci-last_busno; + hose-ops = pci-ops; + +#ifdef CONFIG_PPC32 + /* On 32 bits, limit I/O space to 16MB */ + if (pci-pci_io_size 0x0100) + pci-pci_io_size = 0x0100; + + /* 32 bits needs to map IOs here */ + hose-io_base_virt = ioremap(pci-io_base_phys + pci-io_resource.start, +pci-pci_io_size); + + /* Expect trouble if pci_addr is not 0 */ + if (fsl_pci_primary == pci-dn) + isa_io_base = (unsigned long)hose-io_base_virt; +#endif /* CONFIG_PPC32 */ + + hose-pci_io_size = pci-io_resource.start + pci-pci_io_size; + hose
[PATCH 06/12][v3] pci: fsl: port PCI controller setup code
PCI controller setup code will initialize structure fsl_pci according to PCI dts node and initialize PCI command register and ATMU. The patch uses general API of_pci_parse_bus_range to parse PCI bus range, uses general of_address's API to parse PCI IO/MEM ranges. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ drivers/pci/host/pci-fsl-common.c | 179 +- 1 file changed, 97 insertions(+), 82 deletions(-) diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c index f15b605..e09a0ec 100644 --- a/drivers/pci/host/pci-fsl-common.c +++ b/drivers/pci/host/pci-fsl-common.c @@ -24,6 +24,8 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/of_address.h +#include linux/of_pci.h #include asm/io.h #include asm/prom.h @@ -505,131 +507,144 @@ static void setup_pci_atmu(struct fsl_pci *pci) } } -static void __init setup_pci_cmd(struct pci_controller *hose) +static void __init setup_pci_cmd(struct fsl_pci *pci) { u16 cmd; int cap_x; - early_read_config_word(hose, 0, 0, PCI_COMMAND, cmd); + early_fsl_read_config_word(pci, 0, 0, PCI_COMMAND, cmd); cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + early_fsl_write_config_word(pci, 0, 0, PCI_COMMAND, cmd); - cap_x = early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX); + cap_x = early_fsl_find_capability(pci, 0, 0, PCI_CAP_ID_PCIX); if (cap_x) { int pci_x_cmd = cap_x + PCI_X_CMD; cmd = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E; - early_write_config_word(hose, 0, 0, pci_x_cmd, cmd); - } else { - early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); - } + early_fsl_write_config_word(pci, 0, 0, pci_x_cmd, cmd); + } else + early_fsl_write_config_byte(pci, 0, 0, PCI_LATENCY_TIMER, + 0x80); } -int __init fsl_add_bridge(struct platform_device *pdev, int is_primary) +static int __init +fsl_pci_setup(struct platform_device *pdev, struct fsl_pci *pci) { - int len; - struct pci_controller *hose; - struct resource rsrc; - const int *bus_range; + struct resource *rsrc; u8 hdr_type, progif; - struct device_node *dev; - struct ccsr_pci __iomem *pci; - - dev = pdev-dev.of_node; + struct device_node *dn; + struct of_pci_range range; + struct of_pci_range_parser parser; + int mem = 0; - if (!of_device_is_available(dev)) { - pr_warning(%s: disabled\n, dev-full_name); - return -ENODEV; - } + dn = pdev-dev.of_node; + pci-dn = dn; + pci-dev = pdev-dev; - pr_debug(Adding PCI host bridge %s\n, dev-full_name); + dev_info(pdev-dev, Find controller %s\n, dn-full_name); /* Fetch host bridge registers address */ - if (of_address_to_resource(dev, 0, rsrc)) { - printk(KERN_WARNING Can't get pci register base!); - return -ENOMEM; + rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rsrc) { + dev_err(pdev-dev, Can't get pci register base!); + return -EINVAL; } + dev_info(pdev-dev, REG 0x%016llx..0x%016llx\n, +(u64)rsrc-start, (u64)rsrc-end); - /* Get bus range if any */ - bus_range = of_get_property(dev, bus-range, len); - if (bus_range == NULL || len 2 * sizeof(int)) - printk(KERN_WARNING Can't get bus-range for %s, assume -bus 0\n, dev-full_name); - - pci_add_flags(PCI_REASSIGN_ALL_BUS); - hose = pcibios_alloc_controller(dev); - if (!hose) - return -ENOMEM; + /* Parse pci range resources from device tree */ + if (of_pci_range_parser_init(parser, dn)) { + dev_err(pdev-dev, missing ranges property\n); + return -EINVAL; + } - /* set platform device as the parent */ - hose-parent = pdev-dev; - hose-first_busno = bus_range ? bus_range[0] : 0x0; - hose-last_busno = bus_range ? bus_range[1] : 0xff; + /* Get the I/O and memory ranges from device tree */ + for_each_of_pci_range(parser, range) { + unsigned long restype = range.flags IORESOURCE_TYPE_BITS; + if (restype == IORESOURCE_IO) { + of_pci_range_to_resource(range, dn, +pci-io_resource
[PATCH 11/12][v3] pci: fsl: update PCI EDAC driver
1. The pci-fsl-common driver has set fsl_pci to device as drvdata, so EDAC driver can not call dev_set_drvdata() again. fsl_pci contains regs field to point PCI CCSR, so EDAC may directly use the pointer and not need to call devm_ioremap(). 2. Add mpc85xx_pci_err_remove() to disable PCI error interrupt and delete PCI EDAC from EDAC subsystem. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Added mpc85xx_pci_err_remove() Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 1 + arch/powerpc/sysdev/fsl_pci.h | 6 ++ drivers/edac/mpc85xx_edac.c | 46 +++ drivers/edac/mpc85xx_edac.h | 1 + 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 40d2e1d..4a03e1a 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -236,6 +236,7 @@ void fsl_arch_pci_sys_remove(struct fsl_pci *pci) if (!hose) return; + mpc85xx_pci_err_remove(to_platform_device(pci-dev)); pcibios_free_controller(hose); } diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index ce77aad..ae4dbe2 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -35,11 +35,17 @@ static inline void fsl_pci_assign_primary(void) {} #ifdef CONFIG_EDAC_MPC85XX int mpc85xx_pci_err_probe(struct platform_device *op); +int mpc85xx_pci_err_remove(struct platform_device *op); #else static inline int mpc85xx_pci_err_probe(struct platform_device *op) { return -ENOTSUPP; } +static inline int mpc85xx_pci_err_remove(struct platform_device *op) +{ + return -ENOTSUPP; +} + #endif #ifdef CONFIG_FSL_PCI diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 3eb32f6..14a4116 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -21,6 +21,7 @@ #include linux/of_platform.h #include linux/of_device.h +#include linux/fsl/pci-common.h #include edac_module.h #include edac_core.h #include mpc85xx_edac.h @@ -214,11 +215,13 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) int mpc85xx_pci_err_probe(struct platform_device *op) { + struct fsl_pci *fslpci; struct edac_pci_ctl_info *pci; struct mpc85xx_pci_pdata *pdata; - struct resource r; int res = 0; + fslpci = platform_get_drvdata(op); + if (!devres_open_group(op-dev, mpc85xx_pci_err_probe, GFP_KERNEL)) return -ENOMEM; @@ -239,7 +242,6 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata = pci-pvt_info; pdata-name = mpc85xx_pci_err; pdata-irq = NO_IRQ; - dev_set_drvdata(op-dev, pci); pci-dev = op-dev; pci-mod_name = EDAC_MOD_STR; pci-ctl_name = pdata-name; @@ -250,30 +252,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata-edac_idx = edac_pci_idx++; - res = of_address_to_resource(op-dev.of_node, 0, r); - if (res) { - printk(KERN_ERR %s: Unable to get resource for - PCI err regs\n, __func__); - goto err; - } - /* we only need the error registers */ - r.start += 0xe00; - - if (!devm_request_mem_region(op-dev, r.start, resource_size(r), - pdata-name)) { - printk(KERN_ERR %s: Error while requesting mem region\n, - __func__); - res = -EBUSY; - goto err; - } - - pdata-pci_vbase = devm_ioremap(op-dev, r.start, resource_size(r)); - if (!pdata-pci_vbase) { - printk(KERN_ERR %s: Unable to setup PCI err regs\n, __func__); - res = -ENOMEM; - goto err; - } + pdata-pci_vbase = (void *)fslpci-regs + MPC85XX_PCI_ERR_OFFSET; orig_pci_err_cap_dr = in_be32(pdata-pci_vbase + MPC85XX_PCI_ERR_CAP_DR); @@ -327,20 +307,25 @@ err: } EXPORT_SYMBOL(mpc85xx_pci_err_probe); -static int mpc85xx_pci_err_remove(struct platform_device *op) +int mpc85xx_pci_err_remove(struct platform_device *op) { - struct edac_pci_ctl_info *pci = dev_get_drvdata(op-dev); - struct mpc85xx_pci_pdata *pdata = pci-pvt_info; + struct edac_pci_ctl_info *pci; + struct mpc85xx_pci_pdata *pdata; edac_dbg(0, \n); + pci = edac_pci_del_device(op-dev); + + if (!pci) + return -EINVAL; + + pdata = pci-pvt_info; + out_be32(pdata-pci_vbase + MPC85XX_PCI_ERR_CAP_DR, orig_pci_err_cap_dr); out_be32(pdata-pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en); - edac_pci_del_device(pci-dev); - if (edac_op_state == EDAC_OPSTATE_INT
[PATCH 12/12][v3] pci: fsl: fix function check_pci_ctl_endpt_part
The new FSL PCI driver does not use cfg_addr of pci_controller, we may directly access PCI CCSR using fsl_pci-regs. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v3: The new patch to fix function check_pci_ctl_endpt_part Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.h | 5 - drivers/iommu/fsl_pamu_domain.c | 6 -- include/linux/fsl/pci-common.h | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index ae4dbe2..3176eb2 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -16,11 +16,6 @@ struct platform_device; - -/* FSL PCI controller BRR1 register */ -#define PCI_FSL_BRR1 0xbf8 -#define PCI_FSL_BRR1_VER 0x - extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); extern int mpc83xx_add_bridge(struct device_node *dev); u64 fsl_pci_immrbar_base(struct pci_controller *hose); diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index c857c30..dd7bc25 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -36,6 +36,7 @@ #include asm/pci-bridge.h #include sysdev/fsl_pci.h +#include linux/fsl/pci-common.h #include fsl_pamu_domain.h #include pci.h @@ -908,10 +909,11 @@ static struct iommu_group *get_device_iommu_group(struct device *dev) static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) { u32 version; + struct fsl_pci *pci = fsl_arch_sys_to_pci(pci_ctl); /* Check the PCI controller version number by readding BRR1 register */ - version = in_be32(pci_ctl-cfg_addr + (PCI_FSL_BRR1 2)); - version = PCI_FSL_BRR1_VER; + version = in_be32(pci-regs-block_rev1); + version = PCIE_IP_REV_MASK; /* If PCI controller version is = 0x204 we can partition endpoints*/ if (version = 0x204) return 1; diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h index 84b0801..6112adf 100644 --- a/include/linux/fsl/pci-common.h +++ b/include/linux/fsl/pci-common.h @@ -18,6 +18,7 @@ #define PCIE_LTSSM_L0 0x16/* L0 state */ #define PCIE_IP_REV_2_20x02080202 /* PCIE IP block version Rev2.2 */ #define PCIE_IP_REV_3_00x02080300 /* PCIE IP block version Rev3.0 */ +#define PCIE_IP_REV_MASK 0x #define PIWAR_EN 0x8000 /* Enable */ #define PIWAR_PF 0x2000 /* prefetch */ #define PIWAR_TGI_LOCAL0x00f0 /* target - local memory */ -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2][v2] pci: fsl: derive the common PCI driver to drivers/pci/host
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pci-fsl-common.c and leaves the architecture specific functions which should be implemented in arch related files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v2: 1. rename pci.h to pci-common.h 2. rename pci-fsl.c to pci-fsl-common.c Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 521 +- arch/powerpc/sysdev/fsl_pci.h | 89 .../fsl_pci.c = drivers/pci/host/pci-fsl-common.c | 591 + .../fsl_pci.h = include/linux/fsl/pci-common.h| 45 +- 4 files changed, 7 insertions(+), 1239 deletions(-) copy arch/powerpc/sysdev/fsl_pci.c = drivers/pci/host/pci-fsl-common.c (54%) copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci-common.h (79%) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ccfb50d..26039e3 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -27,6 +27,7 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/fsl/pci-common.h #include asm/io.h #include asm/prom.h @@ -58,57 +59,8 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; - - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = hose-first_busno; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } - - return 0; -} - -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); -} - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - #define MAX_PHYS_ADDR_BITS 40 static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; @@ -132,291 +84,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) -{ - resource_size_t pci_addr = res-start - offset; - resource_size_t phys_addr = res-start; - resource_size_t size = resource_size(res); - u32 flags = 0x80044000; /* enable mem R/W */ - unsigned int i; - - pr_debug(PCI MEM resource start 0x%016llx, size 0x%016llx.\n, - (u64)res-start, (u64)size); - - if (res-flags IORESOURCE_PREFETCH) - flags |= 0x1000; /* enable relaxed ordering */ - - for (i = 0; size 0; i++) { - unsigned int bits = min(ilog2(size), - __ffs(pci_addr | phys_addr)); - - if (index + i = 5) - return -1; - - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); - - pci_addr += (resource_size_t)1U bits; - phys_addr += (resource_size_t)1U bits; - size -= (resource_size_t)1U bits
[PATCH 2/2][v2] pci: fsl: rework PCI driver compatible with Layerscape
The Freescale's Layerscape series processors will use the same PCI controller but change cores from PowerPC to ARM. This patch is to rework FSL PCI driver to support PowerPC and ARM simultaneously. PowerPC uses structure pci_controller to describe PCI controller, but arm uses structure hw_pci and pci_sys_data. They also have different architecture implementation and initialization flow. The architecture-dependent driver will bridge the gap, get the settings from the common driver and initialize the corresponding structure and call the related interface to register PCI controller. The common driver pci-fsl-common.c removes all the architecture-specific code and provides structure fsl_pci to store all the controller settings and the common functionalities that include reading/writing PCI configuration space, parsing dts node and getting the MEM/IO and bus number ranges, setting ATMU and check link status. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- change log: v1-v2: 1. change the driver name from pci-fsl to pci-fsl-common in order to avoid confusion between fsl-pci and pci-fsl. 2. change type of is_pcie and fsl_pci_check_link() to bool. 3. remove __exit macro from fsl_pci_remove(). 4. remove __weak macro from fsl_arch_pci_sys_register() and fsl_arch_pci_sys_remove() because every supported arch must contain the two implementations. Based on upstream master Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274488/ The function has been tested on MPC8315ERDB MPC8572DS P5020DS P3041DS and T4240QDS boards arch/powerpc/Kconfig | 1 + arch/powerpc/sysdev/fsl_pci.c | 147 - drivers/edac/mpc85xx_edac.c | 16 +- drivers/pci/host/Kconfig | 10 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl-common.c | 652 +- include/linux/fsl/pci-common.h| 71 + 7 files changed, 654 insertions(+), 244 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 38f3b7e..7447d97d 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -690,6 +690,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL_COMMON if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 26039e3..40d2e1d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose-private_data; + + /* Update the first bus number */ + if (pci-first_busno != hose-first_busno) + pci-first_busno = hose-first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = hose; + hose.private_data = pci; + bus.ops = pci-ops; + + return bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + bool is_pcie, no_link; + int i; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose-indirect_type PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci-is_pcie; + no_link = !fsl_pci_check_link(pci); if (bus-parent == hose-bus (is_pcie || no_link)) { for (i = 0; i PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci-sys; + + if (!hose
[PATCH 1/2] pci: fsl: derive the common PCI driver to drivers/pci/host
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pci-fsl.c and leaves the architecture-specific functions which should be implemented in arch related files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 521 +- arch/powerpc/sysdev/fsl_pci.h | 89 .../sysdev/fsl_pci.c = drivers/pci/host/pci-fsl.c | 591 + .../sysdev/fsl_pci.h = include/linux/fsl/pci.h| 45 +- 4 files changed, 7 insertions(+), 1239 deletions(-) copy arch/powerpc/sysdev/fsl_pci.c = drivers/pci/host/pci-fsl.c (54%) copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci.h (79%) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ccfb50d..a189ff0 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -27,6 +27,7 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/fsl/pci.h #include asm/io.h #include asm/prom.h @@ -58,57 +59,8 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; - - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = hose-first_busno; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } - - return 0; -} - -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); -} - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - #define MAX_PHYS_ADDR_BITS 40 static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; @@ -132,291 +84,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) -{ - resource_size_t pci_addr = res-start - offset; - resource_size_t phys_addr = res-start; - resource_size_t size = resource_size(res); - u32 flags = 0x80044000; /* enable mem R/W */ - unsigned int i; - - pr_debug(PCI MEM resource start 0x%016llx, size 0x%016llx.\n, - (u64)res-start, (u64)size); - - if (res-flags IORESOURCE_PREFETCH) - flags |= 0x1000; /* enable relaxed ordering */ - - for (i = 0; size 0; i++) { - unsigned int bits = min(ilog2(size), - __ffs(pci_addr | phys_addr)); - - if (index + i = 5) - return -1; - - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); - - pci_addr += (resource_size_t)1U bits; - phys_addr += (resource_size_t)1U bits; - size -= (resource_size_t)1U bits; - } - - return i; -} - -/* atmu setup for fsl pci/pcie controller */ -static void setup_pci_atmu(struct pci_controller *hose
[PATCH 2/2] pci: fsl: rework PCI driver compatible with Layerscape
The Freescale's Layerscape series processors will use the same PCI controller but change cores from PowerPC to ARM. This patch is to rework FSL PCI driver to support PowerPC and ARM simultaneously. PowerPC uses structure pci_controller to describe PCI controller, but arm uses structure hw_pci and pci_sys_data. They also have different architecture implementation and initialization flow. The architecture-dependent driver will bridge the gap, get the settings from the common driver and initialize the corresponding structure and call the related interface to register PCI controller. The common driver pci-fsl.c removes all the architecture-specific code and provides structure fsl_pci to store all the controller settings and the common functionalities that include reading/writing PCI configuration space, parsing dts node and getting the MEM/IO and bus number ranges, setting ATMU and check link status. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274488/ The function has been tested on MPC8315ERDB MPC8572DS P5020DS P3041DS and T4240QDS boards arch/powerpc/Kconfig | 1 + arch/powerpc/sysdev/fsl_pci.c | 147 +- drivers/edac/mpc85xx_edac.c | 16 +- drivers/pci/host/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl.c| 653 +++--- include/linux/fsl/pci.h | 69 + 7 files changed, 653 insertions(+), 241 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 38f3b7e..6fd6348 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -690,6 +690,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index a189ff0..1413257 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,43 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose-private_data; + + /* Update the first bus number */ + if (pci-first_busno != hose-first_busno) + pci-first_busno = hose-first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = hose; + hose.private_data = pci; + bus.ops = pci-ops; + + return bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + int i, is_pcie, no_link; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +127,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose-indirect_type PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci-is_pcie; + no_link = fsl_pci_check_link(pci); if (bus-parent == hose-bus (is_pcie || no_link)) { for (i = 0; i PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +150,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci-sys; + + if (!hose) + return PCIBIOS_SUCCESSFUL; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(hose, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +int fsl_arch_pci_sys_register(struct fsl_pci *pci) +{ + struct pci_controller *hose; + + pci_add_flags(PCI_REASSIGN_ALL_BUS); + hose = pcibios_alloc_controller(pci-dn); + if (!hose
[PATCH 1/2][RFC][v3] pci: fsl: derive the common PCI driver to drivers/pci/host
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pci-fsl.c and leaves the architecture-specific functions which should be implemented in arch related files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master Change log: v3: 1. Add the new patch that only contains the code movement. V2: NULL arch/powerpc/sysdev/fsl_pci.c | 521 +- arch/powerpc/sysdev/fsl_pci.h | 89 .../sysdev/fsl_pci.c = drivers/pci/host/pci-fsl.c | 591 + .../sysdev/fsl_pci.h = include/linux/fsl/pci.h| 40 +- 4 files changed, 7 insertions(+), 1234 deletions(-) copy arch/powerpc/sysdev/fsl_pci.c = drivers/pci/host/pci-fsl.c (54%) copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci.h (81%) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ccfb50d..a189ff0 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -27,6 +27,7 @@ #include linux/log2.h #include linux/slab.h #include linux/uaccess.h +#include linux/fsl/pci.h #include asm/io.h #include asm/prom.h @@ -58,57 +59,8 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; - - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = hose-first_busno; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } - - return 0; -} - -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); -} - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - #define MAX_PHYS_ADDR_BITS 40 static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; @@ -132,291 +84,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static int setup_one_atmu(struct ccsr_pci __iomem *pci, - unsigned int index, const struct resource *res, - resource_size_t offset) -{ - resource_size_t pci_addr = res-start - offset; - resource_size_t phys_addr = res-start; - resource_size_t size = resource_size(res); - u32 flags = 0x80044000; /* enable mem R/W */ - unsigned int i; - - pr_debug(PCI MEM resource start 0x%016llx, size 0x%016llx.\n, - (u64)res-start, (u64)size); - - if (res-flags IORESOURCE_PREFETCH) - flags |= 0x1000; /* enable relaxed ordering */ - - for (i = 0; size 0; i++) { - unsigned int bits = min(ilog2(size), - __ffs(pci_addr | phys_addr)); - - if (index + i = 5) - return -1; - - out_be32(pci-pow[index + i].potar, pci_addr 12); - out_be32(pci-pow[index + i].potear, (u64)pci_addr 44); - out_be32(pci-pow[index + i].powbar, phys_addr 12); - out_be32(pci-pow[index + i].powar, flags | (bits - 1)); - - pci_addr += (resource_size_t)1U bits; - phys_addr += (resource_size_t)1U bits; - size -= (resource_size_t)1U bits; - } - - return i; -} - -/* atmu setup for fsl pci/pcie controller */ -static void setup_pci_atmu(struct pci_controller *hose
[PATCH 2/2][RFC][v3] pci: fsl: rework PCI driver compatible with Layerscape
The Freescale's Layerscape series processors will use the same PCI controller but change cores from PowerPC to ARM. This patch is to rework FSL PCI driver to support PowerPC and ARM simultaneously. PowerPC uses structure pci_controller to describe PCI controller, but arm uses structure hw_pci and pci_sys_data. They also have different architecture implementation and initialization flow. The architecture-dependent driver will bridge the gap, get the settings from the common driver and initialize the corresponding structure and call the related interface to register PCI controller. The common driver pci-fsl.c removes all the architecture-specific code and provides structure fsl_pci to store all the controller settings and the common functionalities that include reading/writing PCI configuration space, parsing dts node and getting the MEM/IO and bus number ranges, setting ATMU and check link status. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master The function has been tested on MPC8315ERDB MPC8572DS P5020DS P3041DS and T4240QDS boards Change log: v3: 1. use 'fsl_arch' as function name prefix of all the architecture-specific hooks. 2. Move PCI compatible definitions from arch/powerpc/sysdev/fsl_pci.c to driver/pci/host/pci-fsl.c v2: 1. Use 'pci' instead of 'pcie' in new file name and file contents. 2. Use iowrite32be()/iowrite32() instead of out_be32/le32() 3. Fix ppc_md.dma_set_mask setting 4. Synchronizes host-first_busno and pci-first_busno. 5. Fix PCI IO space settings 6. Some small changes according to Scott's comments. arch/powerpc/Kconfig | 1 + arch/powerpc/sysdev/fsl_pci.c | 150 +- drivers/edac/mpc85xx_edac.c | 9 - drivers/pci/host/Kconfig | 4 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl.c| 656 +++--- include/linux/fsl/pci.h | 69 + 7 files changed, 648 insertions(+), 242 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6b7530f..657d90f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -691,6 +691,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index a189ff0..4cb12e8 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,43 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose-private_data; + + /* Update the first bus number */ + if (pci-first_busno != hose-first_busno) + pci-first_busno = hose-first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = hose; + hose.private_data = pci; + bus.ops = pci-ops; + + return bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + int i, is_pcie, no_link; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +127,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose-indirect_type PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci-is_pcie; + no_link = fsl_pci_check_link(pci); if (bus-parent == hose-bus (is_pcie || no_link)) { for (i = 0; i PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +150,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci-sys; + + if (!hose) + return PCIBIOS_SUCCESSFUL
[PATCH][RFC][v2] pci: fsl: rework PCIe driver compatible with Layerscape
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pcie-fsl.c and leaves several platform-dependent functions which should be implemented in platform files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master 3.11-rc7 The function has been tested on MPC8315ERDB MPC8572DS P5020DS P3041DS and T4240QDS boards Change log: v2: 1. Use 'pci' instead of 'pcie' in new file name and file contents. 2. Use iowrite32be()/iowrite32() instead of out_be32/le32() 3. Fix ppc_md.dma_set_mask setting 4. Synchronizes host-first_busno and pci-first_busno. 5. Fix PCI IO space settings 6. Some small changes according to Scott's comments. arch/powerpc/Kconfig | 1 + arch/powerpc/sysdev/fsl_pci.c | 610 - arch/powerpc/sysdev/fsl_pci.h | 91 --- drivers/edac/mpc85xx_edac.c| 10 - drivers/pci/host/Kconfig | 4 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-fsl.c | 736 + .../sysdev/fsl_pci.h = include/linux/fsl/pci.h| 107 ++- 8 files changed, 932 insertions(+), 628 deletions(-) create mode 100644 drivers/pci/host/pci-fsl.c copy arch/powerpc/sysdev/fsl_pci.h = include/linux/fsl/pci.h (67%) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9cf59816d..f78484c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -671,6 +671,7 @@ config FSL_SOC config FSL_PCI bool + select PCI_FSL if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 46ac1dd..b3ff28b 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,7 +1,7 @@ /* * MPC83xx/85xx/86xx PCI/PCIE support routing. * - * Copyright 2007-2012 Freescale Semiconductor, Inc. + * Copyright 2007-2013 Freescale Semiconductor, Inc. * Copyright 2008-2009 MontaVista Software, Inc. * * Initial author: Xianghua Xiao x.x...@freescale.com @@ -26,6 +26,7 @@ #include linux/memblock.h #include linux/log2.h #include linux/slab.h +#include linux/fsl/pci.h #include asm/io.h #include asm/prom.h @@ -54,60 +55,17 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header); - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = 0; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } +#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) - return 0; -} +#define MAX_PHYS_ADDR_BITS 40 -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) +u64 fsl_pci64_dma_offset(void) { - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); + return 1ull MAX_PHYS_ADDR_BITS; } -#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) - -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - -#define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; - static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { if (!dev-dma_mask || !dma_supported(dev, dma_mask
[PATCH][RFC] pci: fsl: rework PCIe driver compatible with Layerscape
The Freescale's Layerscape series processors will use ARM cores. The LS1's PCIe controllers is the same as T4240's. So it's better the PCIe controller driver can support PowerPC and ARM simultaneously. This patch is for this purpose. It derives the common functions from arch/powerpc/sysdev/fsl_pci.c to drivers/pci/host/pcie-fsl.c and leaves several platform-dependent functions which should be implemented in platform files. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- Based on upstream master 3.11-rc6 The function has been tested on P5020DS and P3041DS and T4240QDS boards For mpc83xx and mpc86xx, I only did compile test. arch/powerpc/Kconfig | 1 + arch/powerpc/sysdev/fsl_pci.c | 591 ++ arch/powerpc/sysdev/fsl_pci.h | 91 -- drivers/edac/mpc85xx_edac.c | 10 - drivers/pci/host/Kconfig | 4 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-fsl.c | 734 ++ include/linux/fsl/fsl-pcie.h | 176 ++ 8 files changed, 1008 insertions(+), 600 deletions(-) create mode 100644 drivers/pci/host/pcie-fsl.c create mode 100644 include/linux/fsl/fsl-pcie.h diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index dbd9d3c..66b51a8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -671,6 +671,7 @@ config FSL_SOC config FSL_PCI bool + select PCIE_FSL if FSL_SOC_BOOKE || PPC_86xx select PPC_INDIRECT_PCI select PCI_QUIRKS diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 46ac1dd..a05a9e1 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,7 +1,7 @@ /* * MPC83xx/85xx/86xx PCI/PCIE support routing. * - * Copyright 2007-2012 Freescale Semiconductor, Inc. + * Copyright 2007-2013 Freescale Semiconductor, Inc. * Copyright 2008-2009 MontaVista Software, Inc. * * Initial author: Xianghua Xiao x.x...@freescale.com @@ -26,6 +26,7 @@ #include linux/memblock.h #include linux/log2.h #include linux/slab.h +#include linux/fsl/fsl-pcie.h #include asm/io.h #include asm/prom.h @@ -54,60 +55,17 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) return; } -static int fsl_indirect_read_config(struct pci_bus *, unsigned int, - int, int, u32 *); - -static int fsl_pcie_check_link(struct pci_controller *hose) -{ - u32 val = 0; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header); - if (hose-indirect_type PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { - if (hose-ops-read == fsl_indirect_read_config) { - struct pci_bus bus; - bus.number = 0; - bus.sysdata = hose; - bus.ops = hose-ops; - indirect_read_config(bus, 0, PCIE_LTSSM, 4, val); - } else - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, val); - if (val PCIE_LTSSM_L0) - return 1; - } else { - struct ccsr_pci __iomem *pci = hose-private_data; - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */ - val = (in_be32(pci-pex_csr0) PEX_CSR0_LTSSM_MASK) -PEX_CSR0_LTSSM_SHIFT; - if (val != PEX_CSR0_LTSSM_L0) - return 1; - } +#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) - return 0; -} +#define MAX_PHYS_ADDR_BITS 40 -static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) +u64 fsl_pci64_dma_offset(void) { - struct pci_controller *hose = pci_bus_to_host(bus); - - if (fsl_pcie_check_link(hose)) - hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; - else - hose-indirect_type = ~PPC_INDIRECT_TYPE_NO_PCIE_LINK; - - return indirect_read_config(bus, devfn, offset, len, val); + return 1ull MAX_PHYS_ADDR_BITS; } -#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) - -static struct pci_ops fsl_indirect_pcie_ops = -{ - .read = fsl_indirect_read_config, - .write = indirect_write_config, -}; - -#define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull MAX_PHYS_ADDR_BITS; - static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { if (!dev-dma_mask || !dma_supported(dev, dma_mask)) @@ -121,300 +79,36 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev-bus == pci_bus_type) dma_mask = DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_pci64_dma_offset()); } *dev-dma_mask = dma_mask; return 0
[PATCH] powerpc/dts: fix sRIO error interrupt for b4860
For B4 platform, MPIC EISR register is in reversed bitmap order, instead of Error interrupt source 0-31. Bit 0 represents SRC0. the correct ordering is Error interrupt source 0-31. Bit 0 represents SRC31. This patch is to fix sRIO EISR bit value of error interrupt in dts node. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/boot/dts/fsl/b4860si-post.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi index e5cf6c8..9813975 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi @@ -41,7 +41,7 @@ rio { compatible = fsl,srio; - interrupts = 16 2 1 11; + interrupts = 16 2 1 20; #address-cells = 2; #size-cells = 2; fsl,iommu-parent = pamu0; -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/3 v2] powerpc/dts: update MSI bindings doc for MPIC v4.3
Add compatible fsl,mpic-msi-v4.3 for MPIC v4.3. MPIC v4.3 contains MSIIR and MSIIR1. MSIIR supports 8 MSI registers and MSIIR1 supports 16 MSI registers, but uses different IBS and SRS shift. When using MSIR1, the interrupt number is not consecutive. It is hard to use 'msi-available-ranges' to describe the ranges of the available interrupt, so MPIC v4.3 does not support this property. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- v2 log: 1. move msi-available-ranges to optional properties. .../devicetree/bindings/powerpc/fsl/msi-pic.txt| 51 +- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt index 5693877..d82b080 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt @@ -1,21 +1,20 @@ * Freescale MSI interrupt controller Required properties: -- compatible : compatible list, contains 2 entries, +- compatible : compatible list, may contains one or two entries, first is fsl,CHIP-msi, where CHIP is the processor(mpc8610, mpc8572, - etc.) and the second is fsl,mpic-msi or fsl,ipic-msi depending on - the parent type. + etc.) and the second is fsl,mpic-msi or fsl,ipic-msi or + fsl,mpic-msi-v4.3 depending on the parent type and version. If mpic + version is 4.3, the number of MSI registers is increased to 16, MSIIR1 is + provided to access these 16 registers, compatible fsl,mpic-msi-v4.3 + should be used. The first entry is optional, the second entry must be + required. - reg : It may contain one or two regions. The first region should contain the address and the length of the shared message interrupt register set. - The second region should contain the address of aliased MSIIR register for - platforms that have such an alias. - -- msi-available-ranges: use start count style section to define which - msi interrupt can be used in the 256 msi interrupts. This property is - optional, without this, all the 256 MSI interrupts can be used. - Each available range must begin and end on a multiple of 32 (i.e. - no splitting an individual MSI register or the associated PIC interrupt). + The second region should contain the address of aliased MSIIR or MSIIR1 + register for platforms that have such an alias, if using MSIIR1, the second + region must be added because different MSI group has different MSIIR1 offset. - interrupts : each one of the interrupts here is one entry per 32 MSIs, and routed to the host interrupt controller. the interrupts should @@ -28,6 +27,14 @@ Required properties: to MPIC. Optional properties: +- msi-available-ranges: use start count style section to define which + msi interrupt can be used in the 256 msi interrupts. This property is + optional, without this, all the MSI interrupts can be used. + Each available range must begin and end on a multiple of 32 (i.e. + no splitting an individual MSI register or the associated PIC interrupt). + MPIC v4.3 does not support this property because the 32 interrupts of an + individual register are not continuous when using MSIIR1. + - msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register is used for MSI messaging. The address of MSIIR in PCI address space is the MSI message address. @@ -54,6 +61,28 @@ Example: interrupt-parent = mpic; }; + msi@41600 { + compatible = fsl,mpic-msi-v4.3; + reg = 0x41600 0x200 0x44148 4; + interrupts = + 0xe0 0 0 0 + 0xe1 0 0 0 + 0xe2 0 0 0 + 0xe3 0 0 0 + 0xe4 0 0 0 + 0xe5 0 0 0 + 0xe6 0 0 0 + 0xe7 0 0 0 + 0x100 0 0 0 + 0x101 0 0 0 + 0x102 0 0 0 + 0x103 0 0 0 + 0x104 0 0 0 + 0x105 0 0 0 + 0x106 0 0 0 + 0x107 0 0 0; + }; + The Freescale hypervisor and msi-address-64 --- Normally, PCI devices have access to all of CCSR via an ATMU mapping. The -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/3 v2] powerpc/fsl_msi: add MSIIR1 support for MPIC v4.3
The original MPIC MSI bank contains 8 registers, MPIC v4.3 MSI bank contains 16 registers, and this patch adds NR_MSI_REG_MAX and NR_MSI_IRQS_MAX to describe the maximum capability of MSI bank. MPIC v4.3 provides MSIIR1 to index these 16 MSI registers. MSIIR1 uses different bits definition than MSIIR. This patch adds ibs_shift and srs_shift to indicate the bits definition of the MSIIR and MSIIR1, so the same code can handle the MSIIR and MSIIR1 simultaneously. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- v2 log: 1. remove 'msiregs' support. arch/powerpc/sysdev/fsl_msi.c | 132 ++ arch/powerpc/sysdev/fsl_msi.h | 10 +++- 2 files changed, 101 insertions(+), 41 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ab02db3..76d453e 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -28,6 +28,18 @@ #include fsl_msi.h #include fsl_pci.h +#define MSIIR_OFFSET_MASK 0xf +#define MSIIR_IBS_SHIFT0 +#define MSIIR_SRS_SHIFT5 +#define MSIIR1_IBS_SHIFT 4 +#define MSIIR1_SRS_SHIFT 0 +#define MSI_SRS_MASK 0xf +#define MSI_IBS_MASK 0x1f + +#define msi_hwirq(msi, msir_index, intr_index) \ + ((msir_index) (msi)-srs_shift | \ +((intr_index) (msi)-ibs_shift)) + static LIST_HEAD(msi_head); struct fsl_msi_feature { @@ -80,18 +92,19 @@ static const struct irq_domain_ops fsl_msi_host_ops = { static int fsl_msi_init_allocator(struct fsl_msi *msi_data) { - int rc; + int rc, hwirq; - rc = msi_bitmap_alloc(msi_data-bitmap, NR_MSI_IRQS, + rc = msi_bitmap_alloc(msi_data-bitmap, NR_MSI_IRQS_MAX, msi_data-irqhost-of_node); if (rc) return rc; - rc = msi_bitmap_reserve_dt_hwirqs(msi_data-bitmap); - if (rc 0) { - msi_bitmap_free(msi_data-bitmap); - return rc; - } + /* +* Reserve all the hwirqs +* The available hwirqs will be released in fsl_msi_setup_hwirq() +*/ + for (hwirq = 0; hwirq NR_MSI_IRQS_MAX; hwirq++) + msi_bitmap_reserve_hwirq(msi_data-bitmap, hwirq); return 0; } @@ -144,8 +157,9 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, msg-data = hwirq; - pr_debug(%s: allocated srs: %d, ibs: %d\n, - __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); + pr_debug(%s: allocated srs: %d, ibs: %d\n, __func__, +(hwirq msi_data-srs_shift) MSI_SRS_MASK, +(hwirq msi_data-ibs_shift) MSI_IBS_MASK); } static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) @@ -255,7 +269,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) msir_index = cascade_data-index; - if (msir_index = NR_MSI_REG) + if (msir_index = NR_MSI_REG_MAX) cascade_irq = NO_IRQ; irqd_set_chained_irq_inprogress(idata); @@ -285,8 +299,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) intr_index = ffs(msir_value) - 1; cascade_irq = irq_linear_revmap(msi_data-irqhost, - msir_index * IRQS_PER_MSI_REG + - intr_index + have_shift); + msi_hwirq(msi_data, msir_index, + intr_index + have_shift)); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); have_shift += intr_index + 1; @@ -316,7 +330,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) if (msi-list.prev != NULL) list_del(msi-list); - for (i = 0; i NR_MSI_REG; i++) { + for (i = 0; i NR_MSI_REG_MAX; i++) { virq = msi-msi_virqs[i]; if (virq != NO_IRQ) { cascade_data = irq_get_handler_data(virq); @@ -339,7 +353,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, int offset, int irq_index) { struct fsl_msi_cascade_data *cascade_data = NULL; - int virt_msir; + int virt_msir, i; virt_msir = irq_of_parse_and_map(dev-dev.of_node, irq_index); if (virt_msir == NO_IRQ) { @@ -360,6 +374,11 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, irq_set_handler_data(virt_msir, cascade_data); irq_set_chained_handler(virt_msir, fsl_msi_cascade); + /* Release the hwirqs corresponding to this MSI register */ + for (i = 0; i IRQS_PER_MSI_REG; i++) + msi_bitmap_free_hwirqs(msi-bitmap, + msi_hwirq(msi, offset, i), 1); + return 0; } @@ -368,14 +387,13
[PATCH 1/5] powerpc/dts: add MPIC v4.3 dts node
For the latest platform T4 and B4, MPIC controller has been updated to v4.3. This patch adds a new file to describe the latest MPIC. The MSI blocks number is increased to four, the registers number of each block is increased to sixteen. MSIIR1 has been added to access these sixteen MSI registers. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/boot/dts/fsl/b4si-post.dtsi | 2 +- arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi | 153 +++ arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | 2 +- 3 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi diff --git a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi index 7399154..4c617bf 100644 --- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi @@ -204,7 +204,7 @@ }; }; -/include/ qoriq-mpic.dtsi +/include/ qoriq-mpic4.3.dtsi guts: global-utilities@e { compatible = fsl,b4-device-config; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi new file mode 100644 index 000..e2665b8 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi @@ -0,0 +1,153 @@ +/* + * QorIQ MPIC device tree stub [ controller @ offset 0x4 ] + * + * Copyright 2013 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +mpic: pic@4 { + interrupt-controller; + #address-cells = 0; + #interrupt-cells = 4; + reg = 0x4 0x4; + compatible = fsl,mpic; + device_type = open-pic; + clock-frequency = 0x0; +}; + +timer@41100 { + compatible = fsl,mpic-global-timer; + reg = 0x41100 0x100 0x41300 4; + interrupts = 0 0 3 0 + 1 0 3 0 + 2 0 3 0 + 3 0 3 0; +}; + +msi0: msi@41600 { + compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; + reg = 0x41600 0x200 0x44148 4; + msi-available-ranges = 0 0x200; + interrupts = + 0xe0 0 0 0 + 0xe1 0 0 0 + 0xe2 0 0 0 + 0xe3 0 0 0 + 0xe4 0 0 0 + 0xe5 0 0 0 + 0xe6 0 0 0 + 0xe7 0 0 0 + 0x100 0 0 0 + 0x101 0 0 0 + 0x102 0 0 0 + 0x103 0 0 0 + 0x104 0 0 0 + 0x105 0 0 0 + 0x106 0 0 0 + 0x107 0 0 0; +}; + +msi1: msi@41800 { + compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; + reg = 0x41800 0x200 0x45148 4; + msi-available-ranges = 0 0x200; + interrupts = + 0xe8 0 0 0 + 0xe9 0 0 0 + 0xea 0 0 0 + 0xeb 0 0 0 + 0xec 0 0 0 + 0xed 0 0 0 + 0xee 0 0 0 + 0xef 0 0 0 + 0x108 0 0 0 + 0x109 0 0 0 + 0x10a 0 0 0 + 0x10b 0 0 0 + 0x10c 0 0 0 + 0x10d 0 0 0 + 0x10e 0 0 0 + 0x10f 0 0 0; +}; + +msi2: msi@41a00 { + compatible = fsl,mpic-msi, fsl,mpic-msi
[PATCH 2/5] powerpc/fsl_msi: add MSIIR1 support for MPIC v4.3
MPIC controller v4.3 provides MSIIR1 to index 16 MSI registers. MSIIR can only index 8 MSI registers. MSIIR1 uses different bits definition than MSIIR. This patch adds ibs_shift and srs_shift to indicate the bits definition of the MSIIR and MSIIR1, so the same code can handle the MSIIR and MSIIR1 simultaneously. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/sysdev/fsl_msi.c | 62 ++- arch/powerpc/sysdev/fsl_msi.h | 4 ++- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ab02db3..34510b7 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -28,6 +28,18 @@ #include fsl_msi.h #include fsl_pci.h +#define MSIIR_OFFSET_MASK 0xf +#define MSIIR_IBS_SHIFT0 +#define MSIIR_SRS_SHIFT5 +#define MSIIR1_IBS_SHIFT 4 +#define MSIIR1_SRS_SHIFT 0 +#define MSI_SRS_MASK 0xf +#define MSI_IBS_MASK 0x1f + +#define msi_hwirq(msi, msir_index, intr_index) \ + ((msir_index) (msi)-srs_shift | \ +((intr_index) (msi)-ibs_shift)) + static LIST_HEAD(msi_head); struct fsl_msi_feature { @@ -80,18 +92,19 @@ static const struct irq_domain_ops fsl_msi_host_ops = { static int fsl_msi_init_allocator(struct fsl_msi *msi_data) { - int rc; + int rc, hwirq; rc = msi_bitmap_alloc(msi_data-bitmap, NR_MSI_IRQS, msi_data-irqhost-of_node); if (rc) return rc; - rc = msi_bitmap_reserve_dt_hwirqs(msi_data-bitmap); - if (rc 0) { - msi_bitmap_free(msi_data-bitmap); - return rc; - } + /* +* Reserve all the hwirqs +* The available hwirqs will be released in fsl_msi_setup_hwirq() +*/ + for (hwirq = 0; hwirq NR_MSI_IRQS; hwirq++) + msi_bitmap_reserve_hwirq(msi_data-bitmap, hwirq); return 0; } @@ -144,8 +157,9 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, msg-data = hwirq; - pr_debug(%s: allocated srs: %d, ibs: %d\n, - __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); + pr_debug(%s: allocated srs: %d, ibs: %d\n, __func__, +(hwirq msi_data-srs_shift) MSI_SRS_MASK, +(hwirq msi_data-ibs_shift) MSI_IBS_MASK); } static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) @@ -285,8 +299,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) intr_index = ffs(msir_value) - 1; cascade_irq = irq_linear_revmap(msi_data-irqhost, - msir_index * IRQS_PER_MSI_REG + - intr_index + have_shift); + msi_hwirq(msi_data, msir_index, + intr_index + have_shift)); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); have_shift += intr_index + 1; @@ -339,7 +353,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, int offset, int irq_index) { struct fsl_msi_cascade_data *cascade_data = NULL; - int virt_msir; + int virt_msir, i; virt_msir = irq_of_parse_and_map(dev-dev.of_node, irq_index); if (virt_msir == NO_IRQ) { @@ -360,6 +374,11 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, irq_set_handler_data(virt_msir, cascade_data); irq_set_chained_handler(virt_msir, fsl_msi_cascade); + /* Release the hwirqs corresponding to this MSI register */ + for (i = 0; i IRQS_PER_MSI_REG; i++) + msi_bitmap_free_hwirqs(msi-bitmap, + msi_hwirq(msi, offset, i), 1); + return 0; } @@ -368,7 +387,7 @@ static int fsl_of_msi_probe(struct platform_device *dev) { const struct of_device_id *match; struct fsl_msi *msi; - struct resource res; + struct resource res, msiir; int err, i, j, irq_index, count; int rc; const u32 *p; @@ -421,10 +440,29 @@ static int fsl_of_msi_probe(struct platform_device *dev) } msi-msiir_offset = features-msiir_offset + (res.start 0xf); + + /* +* First read the MSIIR/MSIIR1 offset from dts +* If failure use the hardcode MSIIR offset +*/ + if (of_address_to_resource(dev-dev.of_node, 1, msiir)) + msi-msiir_offset = features-msiir_offset + + (res.start MSIIR_OFFSET_MASK); + else + msi-msiir_offset = msiir.start
[PATCH 3/5] powerpc/dts: update MSI bindings doc for MPIC v4.3
Add compatible fsl,mpic-msi-v4.3 for MPIC v4.3. MPIC v4.3 contains MSIIR and MSIIR1. MSIIR supports 8 MSI registers and MSIIR1 supports 16 MSI registers, but uses different IBS and SRS shift. When using MSIR1, the interrupt number is not consecutive. It is hard to use 'msi-available-ranges' to describe the ranges of the available interrupt and the ranges are related to the application, rather than the description of the hardware. this patch also removes 'msi-available-ranges' property. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- .../devicetree/bindings/powerpc/fsl/msi-pic.txt| 49 ++ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt index 5693877..e851e93 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt @@ -1,26 +1,23 @@ * Freescale MSI interrupt controller Required properties: -- compatible : compatible list, contains 2 entries, +- compatible : compatible list, may contains one or two entries, first is fsl,CHIP-msi, where CHIP is the processor(mpc8610, mpc8572, - etc.) and the second is fsl,mpic-msi or fsl,ipic-msi depending on - the parent type. + etc.) and the second is fsl,mpic-msi or fsl,ipic-msi or + fsl,mpic-msi-v4.3 depending on the parent type and version. If mpic + version is 4.3, the number of MSI registers is increased to 16, MSIIR1 is + provided to access these 16 registers, compatible fsl,mpic-msi-v4.3 + should be used. - reg : It may contain one or two regions. The first region should contain the address and the length of the shared message interrupt register set. - The second region should contain the address of aliased MSIIR register for - platforms that have such an alias. - -- msi-available-ranges: use start count style section to define which - msi interrupt can be used in the 256 msi interrupts. This property is - optional, without this, all the 256 MSI interrupts can be used. - Each available range must begin and end on a multiple of 32 (i.e. - no splitting an individual MSI register or the associated PIC interrupt). + The second region should contain the address of aliased MSIIR or MSIIR1 + register for platforms that have such an alias, if using MSIIR1, the second + region must be added because different MSI group has different MSIRR1 offset. - interrupts : each one of the interrupts here is one entry per 32 MSIs, and routed to the host interrupt controller. the interrupts should - be set as edge sensitive. If msi-available-ranges is present, only - the interrupts that correspond to available ranges shall be present. + be set as edge sensitive. - interrupt-parent: the phandle for the interrupt controller that services interrupts for this device. for 83xx cpu, the interrupts @@ -39,20 +36,18 @@ Optional properties: Example: msi@41600 { - compatible = fsl,mpc8610-msi, fsl,mpic-msi; - reg = 0x41600 0x80; - msi-available-ranges = 0 0x100; - interrupts = - 0xe0 0 - 0xe1 0 - 0xe2 0 - 0xe3 0 - 0xe4 0 - 0xe5 0 - 0xe6 0 - 0xe7 0; - interrupt-parent = mpic; - }; + compatible = fsl,mpic-msi; + reg = 0x41600 0x200 0x44140 4; + interrupts = + 0xe0 0 0 0 + 0xe1 0 0 0 + 0xe2 0 0 0 + 0xe3 0 0 0 + 0xe4 0 0 0 + 0xe5 0 0 0 + 0xe6 0 0 0 + 0xe7 0 0 0; +}; The Freescale hypervisor and msi-address-64 --- -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 5/5] powerpc/fsl_msi: add 'msiregs' kernel parameter
1. Only MSIIR1 can index 16 MSI registers, but when using MSIIR1 the IRQs of a register are not continuous. for example, the first register irq values are 0x0, 0x10, 0x20, 0x30 ... 0x1f0. So it is hard to use 'msi-available-ranges' property to indicate the available ranges and 'msi-available-ranges' property has been removed from dts node, so this patch removes the related code. 2. Add 'msiregs' kernel parameter instead of 'msi-available-ranges' functionality. 'msiregs' is used to indicate the available MSI registers ranges and uses a colon ':' to separate the multiple banks. The range representation format is 'start-end', 'start' and 'end' are integers describe the start and end register index, the available registers lies between start and end and not include end. For example, the available register x satisfying start = x end. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/sysdev/fsl_msi.c | 118 -- arch/powerpc/sysdev/fsl_msi.h | 1 + 2 files changed, 80 insertions(+), 39 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 34510b7..db382ef9b 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -52,6 +52,60 @@ struct fsl_msi_cascade_data { int index; }; +struct msi_reg_range { + u32 start; + u32 end; +}; + +static struct msi_reg_range msiregs[NR_MSI_BANK] = { + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, +}; + +/* + * Handle 'msiregs' parameter. + * msiregs is used to indicate the available MSI registers range and + * uses colon ':' to separate the multiple banks ranges. + * For each bank, the registers range format is 'start-end' + * start and end are integers, used to the indicate the start and end + * register index. The range is a set of real numbers that lies between + * start and end but not include end. For example, the set of all numbers + * x satisfying start = x end. + * if no range specified, driver will use the default range including all + * the registers. + * if you do no want to use this bank, you can set range as '0-0' + * For example msiregs=0-16:0-0::0-2 + */ +static int msi_regs_setup(char *s) +{ + int bank = 0; + char *p; + struct msi_reg_range *range; + + while ((p = strsep(s, :)) != NULL) { + int start = 0, end = NR_MSI_REG; + + if (bank = NR_MSI_BANK) + break; + range = msiregs[bank]; + + if ((*p != '\0') (sscanf(p, %d-%d, start, end) 1)) + pr_err(msiregs correct format is: start-end\n); + + /* Ok, gets the specified value */ + range-start = start; + range-end = end; + pr_info(MSI bank%d available regs range is %d-%d\n, +bank, range-start, range-end); + bank++; + } + return 1; +} + +__setup(msiregs=, msi_regs_setup); + static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) { return in_be32(base + (reg 2)); @@ -350,7 +404,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) static struct lock_class_key fsl_msi_irq_class; static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, - int offset, int irq_index) + int irq_index) { struct fsl_msi_cascade_data *cascade_data = NULL; int virt_msir, i; @@ -369,7 +423,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, } irq_set_lockdep_class(virt_msir, fsl_msi_irq_class); msi-msi_virqs[irq_index] = virt_msir; - cascade_data-index = offset; + cascade_data-index = irq_index; cascade_data-msi_data = msi; irq_set_handler_data(virt_msir, cascade_data); irq_set_chained_handler(virt_msir, fsl_msi_cascade); @@ -377,7 +431,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, /* Release the hwirqs corresponding to this MSI register */ for (i = 0; i IRQS_PER_MSI_REG; i++) msi_bitmap_free_hwirqs(msi-bitmap, - msi_hwirq(msi, offset, i), 1); + msi_hwirq(msi, irq_index, i), 1); return 0; } @@ -387,21 +441,29 @@ static int fsl_of_msi_probe(struct platform_device *dev) { const struct of_device_id *match; struct fsl_msi *msi; + static int bank; + struct msi_reg_range *range; struct resource res, msiir; - int err, i, j, irq_index, count; + int err, irq_index, count; int rc; - const u32 *p; const struct fsl_msi_feature *features; - int len; - u32 offset; - static const u32 all_avail
[PATCH 4/5] powerpc/dts: remove msi-available-ranges property
For MPIC v4.3 MSIIR supports 8 MSI registers and MSIIR1 supports 16 MSI registers, but uses different IBS and SRS shift. For the first register, when using MSIIR we will get the irqs 0x0 0x1 0x2 ...0x1f, but when using MSIIR1, the irqs are 0x0 0x10 0x20 ... 0x1f0 It is hard to describe the available irqs using property 'msi-available-ranges'. The patch removes this property. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi | 1 - arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi| 3 --- arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi | 4 3 files changed, 8 deletions(-) diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi index 71c30eb..1ac4f23 100644 --- a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi +++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi @@ -66,7 +66,6 @@ message@41400 { msi@41600 { compatible = fsl,mpic-msi; reg = 0x41600 0x80; - msi-available-ranges = 0 0x100; interrupts = 0xe0 0 0 0 0xe1 0 0 0 diff --git a/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi index 08f4227..cf7355c 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi @@ -54,7 +54,6 @@ timer@41100 { msi0: msi@41600 { compatible = fsl,mpic-msi; reg = 0x41600 0x200 0x44140 4; - msi-available-ranges = 0 0x100; interrupts = 0xe0 0 0 0 0xe1 0 0 0 @@ -69,7 +68,6 @@ msi0: msi@41600 { msi1: msi@41800 { compatible = fsl,mpic-msi; reg = 0x41800 0x200 0x45140 4; - msi-available-ranges = 0 0x100; interrupts = 0xe8 0 0 0 0xe9 0 0 0 @@ -84,7 +82,6 @@ msi1: msi@41800 { msi2: msi@41a00 { compatible = fsl,mpic-msi; reg = 0x41a00 0x200 0x46140 4; - msi-available-ranges = 0 0x100; interrupts = 0xf0 0 0 0 0xf1 0 0 0 diff --git a/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi index e2665b8..8a997ea 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-mpic4.3.dtsi @@ -54,7 +54,6 @@ timer@41100 { msi0: msi@41600 { compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; reg = 0x41600 0x200 0x44148 4; - msi-available-ranges = 0 0x200; interrupts = 0xe0 0 0 0 0xe1 0 0 0 @@ -77,7 +76,6 @@ msi0: msi@41600 { msi1: msi@41800 { compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; reg = 0x41800 0x200 0x45148 4; - msi-available-ranges = 0 0x200; interrupts = 0xe8 0 0 0 0xe9 0 0 0 @@ -100,7 +98,6 @@ msi1: msi@41800 { msi2: msi@41a00 { compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; reg = 0x41a00 0x200 0x46148 4; - msi-available-ranges = 0 0x200; interrupts = 0xf0 0 0 0 0xf1 0 0 0 @@ -123,7 +120,6 @@ msi2: msi@41a00 { msi3: msi@41c00 { compatible = fsl,mpic-msi, fsl,mpic-msi-v4.3; reg = 0x41c00 0x200 0x47148 4; - msi-available-ranges = 0 0x200; interrupts = 0xf8 0 0 0 0xf9 0 0 0 -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc/fsl: add property 'reg' to pcie@0 node
The property 'reg' is used to identify the PCIe device. if there is no 'reg' the PCI driver can not find PCI device node corresponding to PCI controller, and can not map the interrupts. So all the INTx interrupts can not be used. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com --- arch/powerpc/boot/dts/fsl/b4si-post.dtsi| 1 + arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | 4 2 files changed, 5 insertions(+) diff --git a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi index 7399154..d82c8da 100644 --- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi @@ -49,6 +49,7 @@ interrupts = 20 2 0 0; fsl,iommu-parent = pamu0; pcie@0 { + reg = 0 0 0 0 0; #interrupt-cells = 1; #size-cells = 2; #address-cells = 3; diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi index bd611a9..3a6179f 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi @@ -48,6 +48,7 @@ bus-range = 0x0 0xff; interrupts = 20 2 0 0; pcie@0 { + reg = 0 0 0 0 0; #interrupt-cells = 1; #size-cells = 2; #address-cells = 3; @@ -74,6 +75,7 @@ bus-range = 0 0xff; interrupts = 21 2 0 0; pcie@0 { + reg = 0 0 0 0 0; #interrupt-cells = 1; #size-cells = 2; #address-cells = 3; @@ -100,6 +102,7 @@ bus-range = 0x0 0xff; interrupts = 22 2 0 0; pcie@0 { + reg = 0 0 0 0 0; #interrupt-cells = 1; #size-cells = 2; #address-cells = 3; @@ -126,6 +129,7 @@ bus-range = 0x0 0xff; interrupts = 23 2 0 0; pcie@0 { + reg = 0 0 0 0 0; #interrupt-cells = 1; #size-cells = 2; #address-cells = 3; -- 1.8.1.2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH][v2] powerpc/fsl-pci: use 'Header Type' to identify PCIE mode
The original code uses 'Programming Interface' field to judge if PCIE is EP or RC mode, however, some latest silicons do not support this functionality. According to PCIE specification, 'Header Type' offset 0x0e is used to indicate header type, so change code to use 'Header Type' field to judge PCIE mode. Because FSL PCI controller does not support 'Header Type', patch still uses 'Programming Interface' to identify PCI mode. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com Signed-off-by: Roy Zang tie-fei.z...@freescale.com --- Change log: v2 - keep the original PCI initialization order according to kumar's recommendations. arch/powerpc/sysdev/fsl_pci.c | 37 - 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index c37f461..468e76c 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -38,15 +38,15 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci; static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) { - u8 progif; + u8 hdr_type; /* if we aren't a PCIe don't bother */ if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) return; /* if we aren't in host mode don't bother */ - pci_read_config_byte(dev, PCI_CLASS_PROG, progif); - if (progif 0x1) + pci_read_config_byte(dev, PCI_HEADER_TYPE, hdr_type); + if ((hdr_type 0x7f) != PCI_HEADER_TYPE_BRIDGE) return; dev-class = PCI_CLASS_BRIDGE_PCI 8; @@ -425,7 +425,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) struct pci_controller *hose; struct resource rsrc; const int *bus_range; - u8 progif; + u8 hdr_type, progif; if (!of_device_is_available(dev)) { pr_warning(%s: disabled\n, dev-full_name); @@ -457,15 +457,17 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, PPC_INDIRECT_TYPE_BIG_ENDIAN); - early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, progif); - if ((progif 1) == 1) { - /* unmap cfg_data cfg_addr separately if not on same page */ - if (((unsigned long)hose-cfg_data PAGE_MASK) != - ((unsigned long)hose-cfg_addr PAGE_MASK)) - iounmap(hose-cfg_data); - iounmap(hose-cfg_addr); - pcibios_free_controller(hose); - return -ENODEV; + if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { + /* For PCIE read HEADER_TYPE to identify controler mode */ + early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, hdr_type); + if ((hdr_type 0x7f) != PCI_HEADER_TYPE_BRIDGE) + goto no_bridge; + + } else { + /* For PCI read PROG to identify controller mode */ + early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, progif); + if ((progif 1) == 1) + goto no_bridge; } setup_pci_cmd(hose); @@ -494,6 +496,15 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) setup_pci_atmu(hose, rsrc); return 0; + +no_bridge: + /* unmap cfg_data cfg_addr separately if not on same page */ + if (((unsigned long)hose-cfg_data PAGE_MASK) != + ((unsigned long)hose-cfg_addr PAGE_MASK)) + iounmap(hose-cfg_data); + iounmap(hose-cfg_addr); + pcibios_free_controller(hose); + return -ENODEV; } #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc/fsl-pci: use 'Header Type' to identify PCIE mode
The original code uses 'Programming Interface' field to judge if PCIE is EP or RC mode, however, some latest silicons do not support this functionality. According to PCIE specification, 'Header Type' offset 0x0e is used to indicate header type, so change code to use 'Header Type' field to judge PCIE mode. Because FSL PCI controller does not support 'Header Type', patch still uses 'Programming Interface' to identify PCI mode. Signed-off-by: Minghuan Lian minghuan.l...@freescale.com Signed-off-by: Roy Zang tie-fei.z...@freescale.com --- arch/powerpc/sysdev/fsl_pci.c | 38 +++--- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index c37f461..43d30df 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -38,15 +38,15 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci; static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev) { - u8 progif; + u8 hdr_type; /* if we aren't a PCIe don't bother */ if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) return; /* if we aren't in host mode don't bother */ - pci_read_config_byte(dev, PCI_CLASS_PROG, progif); - if (progif 0x1) + pci_read_config_byte(dev, PCI_HEADER_TYPE, hdr_type); + if ((hdr_type 0x7f) != PCI_HEADER_TYPE_BRIDGE) return; dev-class = PCI_CLASS_BRIDGE_PCI 8; @@ -425,7 +425,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) struct pci_controller *hose; struct resource rsrc; const int *bus_range; - u8 progif; + u8 hdr_type, progif; if (!of_device_is_available(dev)) { pr_warning(%s: disabled\n, dev-full_name); @@ -457,25 +457,24 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, PPC_INDIRECT_TYPE_BIG_ENDIAN); - early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, progif); - if ((progif 1) == 1) { - /* unmap cfg_data cfg_addr separately if not on same page */ - if (((unsigned long)hose-cfg_data PAGE_MASK) != - ((unsigned long)hose-cfg_addr PAGE_MASK)) - iounmap(hose-cfg_data); - iounmap(hose-cfg_addr); - pcibios_free_controller(hose); - return -ENODEV; - } - setup_pci_cmd(hose); /* check PCI express link status */ if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { + /* For PCIE read HEADER_TYPE to identify controler mode */ + early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, hdr_type); + if ((hdr_type 0x7f) != PCI_HEADER_TYPE_BRIDGE) + goto no_bridge; + hose-indirect_type |= PPC_INDIRECT_TYPE_EXT_REG | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; if (fsl_pcie_check_link(hose)) hose-indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; + } else { + /* For PCI read PROG to identify controller mode */ + early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, progif); + if ((progif 1) == 1) + goto no_bridge; } printk(KERN_INFO Found FSL PCI host bridge at 0x%016llx. @@ -494,6 +493,15 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) setup_pci_atmu(hose, rsrc); return 0; + +no_bridge: + /* unmap cfg_data cfg_addr separately if not on same page */ + if (((unsigned long)hose-cfg_data PAGE_MASK) != + ((unsigned long)hose-cfg_addr PAGE_MASK)) + iounmap(hose-cfg_data); + iounmap(hose-cfg_addr); + pcibios_free_controller(hose); + return -ENODEV; } #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev