On Wed, Nov 05, 2014 at 04:45:11PM +0800, Minghuan Lian wrote: > Add support for Freescale Layerscape PCIe controller. This driver > re-uses the designware core code. > > Signed-off-by: Minghuan Lian <Minghuan.Lian@xxxxxxxxxxxxx> Applied with Arnd's ack to pci/host-layerscape for v3.19, thanks! > --- > Based on pci-next branch > > Change log: > v6: > 1. remove MSI support. MSI driver will be implemented in a separate file > 2. remove bitrev() because SCFG is set bit reverse mode as default. > > v5: > 1. Add MAINTAINERS information > 2. Remove unnecessary NULL pointer check > 3. Use dev_dbg instead of dev_err in ls_pcie_msi_irq_handler() > > v4: > 1. Add 'depends on OF' to Kconfig > > v3: > 1. Add prefechable mem region and adjust mem region > 2. Rename 'pcie-scfg' to 'fsl,pcie-scfg' > 3. Change MSI interrupt handler > 4. Use module_platform_driver_probe instead of subsys_initcall > > v2: > 1. Add pcie-scfg to link scfg device node and remove "fsl, ls-pcie" compatible > 2. Use regmap API to access scfg. > 3. remove ls1021 PCI device ID. > 4. remove unused irq pme_irq and ls_pcie_list. > 5. Do not set scfg bit reverse mode > > .../devicetree/bindings/pci/layerscape-pci.txt | 42 +++++ > MAINTAINERS | 10 ++ > drivers/pci/host/Kconfig | 8 + > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pci-layerscape.c | 179 +++++++++++++++++++++ > 5 files changed, 240 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pci/layerscape-pci.txt > create mode 100644 drivers/pci/host/pci-layerscape.c > > diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt > new file mode 100644 > index 0000000..40749eb > --- /dev/null > +++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt > @@ -0,0 +1,42 @@ > +Freescale Layerscape PCIe controller > + > +This PCIe host controller is based on the Synopsis Designware PCIe IP > +and thus inherits all the common properties defined in designware-pcie.txt. > + > +Required properties: > +- compatible: should contain the platform identifier such as "fsl,ls1021a-pcie" > +- reg: base addresses and lengths of the PCIe controller > +- interrupts: A list of interrupt outputs of the controller. Must contain an > + entry for each entry in the interrupt-names property. > +- interrupt-names: Must include the following entries: > + "intr": The interrupt that is asserted for controller interrupts > +- fsl,pcie-scfg: Must include two entries. > + The first entry must be a link to the SCFG device node > + The second entry must be '0' or '1' based on physical PCIe controller index. > + used to get SCFG PEXN registers > + > +Example: > + > + pcie@3400000 { > + compatible = "fsl,ls1021a-pcie", "snps,dw-pcie"; > + reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */ > + 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ > + reg-names = "regs", "config"; > + interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */ > + interrupt-names = "intr"; > + fsl,pcie-scfg = <&scfg 0>; > + #address-cells = <3>; > + #size-cells = <2>; > + device_type = "pci"; > + num-lanes = <4>; > + bus-range = <0x0 0xff>; > + ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */ > + 0xc2000000 0x0 0x20000000 0x40 0x20000000 0x0 0x20000000 /* prefetchable memory */ > + 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ > + #interrupt-cells = <1>; > + interrupt-map-mask = <0 0 0 7>; > + interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, > + <0000 0 0 2 &gic GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, > + <0000 0 0 3 &gic GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, > + <0000 0 0 4 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; > + }; > diff --git a/MAINTAINERS b/MAINTAINERS > index a20df9b..7853d1b 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -6983,6 +6983,16 @@ S: Maintained > F: Documentation/devicetree/bindings/pci/xgene-pci.txt > F: drivers/pci/host/pci-xgene.c > > +PCIe DRIVER FOR FREESCALE LAYERSCAPE > +M: Minghuan Lian <minghuan.Lian@xxxxxxxxxxxxx> > +M: Mingkai Hu <mingkai.hu@xxxxxxxxxxxxx> > +M: Roy Zang <tie-fei.zang@xxxxxxxxxxxxx> > +L: linuxppc-dev@xxxxxxxxxxxxxxxx > +L: linux-pci@xxxxxxxxxxxxxxx > +L: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > +S: Maintained > +F: drivers/pci/host/pci-layerscape.c > + > PCI DRIVER FOR IMX6 > M: Richard Zhu <r65037@xxxxxxxxxxxxx> > M: Lucas Stach <l.stach@xxxxxxxxxxxxxx> > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig > index 3dc25fa..8ac69aa 100644 > --- a/drivers/pci/host/Kconfig > +++ b/drivers/pci/host/Kconfig > @@ -91,4 +91,12 @@ config PCI_XGENE > There are 5 internal PCIe ports available. Each port is GEN3 capable > and have varied lanes from x1 to x8. > > +config PCI_LAYERSCAPE > + bool "Freescale Layerscape PCIe controller" > + depends on OF > + select PCIE_DW > + select MFD_SYSCON > + help > + Say Y here if you want PCIe controller support on Layerscape SoCs. > + > endmenu > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile > index 26b3461..44c2699 100644 > --- a/drivers/pci/host/Makefile > +++ b/drivers/pci/host/Makefile > @@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o > obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o > obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o > obj-$(CONFIG_PCI_XGENE) += pci-xgene.o > +obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o > diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c > new file mode 100644 > index 0000000..6697b1a > --- /dev/null > +++ b/drivers/pci/host/pci-layerscape.c > @@ -0,0 +1,179 @@ > +/* > + * PCIe host controller driver for Freescale Layerscape SoCs > + * > + * Copyright (C) 2014 Freescale Semiconductor. > + * > + * Author: Minghuan Lian <Minghuan.Lian@xxxxxxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/kernel.h> > +#include <linux/delay.h> > +#include <linux/interrupt.h> > +#include <linux/module.h> > +#include <linux/of_pci.h> > +#include <linux/of_platform.h> > +#include <linux/of_irq.h> > +#include <linux/of_address.h> > +#include <linux/pci.h> > +#include <linux/platform_device.h> > +#include <linux/resource.h> > +#include <linux/mfd/syscon.h> > +#include <linux/regmap.h> > + > +#include "pcie-designware.h" > + > +/* PEX1/2 Misc Ports Status Register */ > +#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) > +#define LTSSM_STATE_SHIFT 20 > +#define LTSSM_STATE_MASK 0x3f > +#define LTSSM_PCIE_L0 0x11 /* L0 state */ > + > +/* Symbol Timer Register and Filter Mask Register 1 */ > +#define PCIE_STRFMR1 0x71c > + > +struct ls_pcie { > + struct list_head node; > + struct device *dev; > + struct pci_bus *bus; > + void __iomem *dbi; > + struct regmap *scfg; > + struct pcie_port pp; > + int index; > + int msi_irq; > +}; > + > +#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) > + > +static int ls_pcie_link_up(struct pcie_port *pp) > +{ > + u32 state; > + struct ls_pcie *pcie = to_ls_pcie(pp); > + > + regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); > + state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; > + > + if (state < LTSSM_PCIE_L0) > + return 0; > + > + return 1; > +} > + > +static void ls_pcie_host_init(struct pcie_port *pp) > +{ > + struct ls_pcie *pcie = to_ls_pcie(pp); > + int count = 0; > + u32 val; > + > + dw_pcie_setup_rc(pp); > + > + while (!ls_pcie_link_up(pp)) { > + usleep_range(100, 1000); > + count++; > + if (count >= 200) { > + dev_err(pp->dev, "phy link never came up\n"); > + return; > + } > + } > + > + /* > + * LS1021A Workaround for internal TKT228622 > + * to fix the INTx hang issue > + */ > + val = ioread32(pcie->dbi + PCIE_STRFMR1); > + val &= 0xffff; > + iowrite32(val, pcie->dbi + PCIE_STRFMR1); > +} > + > +static struct pcie_host_ops ls_pcie_host_ops = { > + .link_up = ls_pcie_link_up, > + .host_init = ls_pcie_host_init, > +}; > + > +static int ls_add_pcie_port(struct ls_pcie *pcie) > +{ > + struct pcie_port *pp; > + int ret; > + > + pp = &pcie->pp; > + pp->dev = pcie->dev; > + pp->dbi_base = pcie->dbi; > + pp->root_bus_nr = -1; > + pp->ops = &ls_pcie_host_ops; > + > + ret = dw_pcie_host_init(pp); > + if (ret) { > + dev_err(pp->dev, "failed to initialize host\n"); > + return ret; > + } > + > + return 0; > +} > + > +static int __init ls_pcie_probe(struct platform_device *pdev) > +{ > + struct ls_pcie *pcie; > + struct resource *dbi_base; > + u32 index[2]; > + int ret; > + > + pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); > + if (!pcie) > + return -ENOMEM; > + > + pcie->dev = &pdev->dev; > + > + dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); > + if (!dbi_base) { > + dev_err(&pdev->dev, "missing *regs* space\n"); > + return -ENODEV; > + } > + > + pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); > + if (IS_ERR(pcie->dbi)) > + return PTR_ERR(pcie->dbi); > + > + pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, > + "fsl,pcie-scfg"); > + if (IS_ERR(pcie->scfg)) { > + dev_err(&pdev->dev, "No syscfg phandle specified\n"); > + return PTR_ERR(pcie->scfg); > + } > + > + ret = of_property_read_u32_array(pdev->dev.of_node, > + "fsl,pcie-scfg", index, 2); > + if (ret) > + return ret; > + pcie->index = index[1]; > + > + ret = ls_add_pcie_port(pcie); > + if (ret < 0) > + return ret; > + > + platform_set_drvdata(pdev, pcie); > + > + return 0; > +} > + > +static const struct of_device_id ls_pcie_of_match[] = { > + { .compatible = "fsl,ls1021a-pcie" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, ls_pcie_of_match); > + > +static struct platform_driver ls_pcie_driver = { > + .driver = { > + .name = "layerscape-pcie", > + .owner = THIS_MODULE, > + .of_match_table = ls_pcie_of_match, > + }, > +}; > + > +module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe); > + > +MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@xxxxxxxxxxxxx>"); > +MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver"); > +MODULE_LICENSE("GPL v2"); > -- > 1.9.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html