aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pci/layerscape-pci.txt42
-rw-r--r--MAINTAINERS10
-rw-r--r--drivers/pci/host/Kconfig8
-rw-r--r--drivers/pci/host/Makefile1
-rw-r--r--drivers/pci/host/pci-layerscape.c179
5 files changed, 240 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
new file mode 100644
index 000000000000..6286f049bf18
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -0,0 +1,42 @@
1Freescale Layerscape PCIe controller
2
3This PCIe host controller is based on the Synopsis Designware PCIe IP
4and thus inherits all the common properties defined in designware-pcie.txt.
5
6Required properties:
7- compatible: should contain the platform identifier such as "fsl,ls1021a-pcie"
8- reg: base addresses and lengths of the PCIe controller
9- interrupts: A list of interrupt outputs of the controller. Must contain an
10 entry for each entry in the interrupt-names property.
11- interrupt-names: Must include the following entries:
12 "intr": The interrupt that is asserted for controller interrupts
13- fsl,pcie-scfg: Must include two entries.
14 The first entry must be a link to the SCFG device node
15 The second entry must be '0' or '1' based on physical PCIe controller index.
16 This is used to get SCFG PEXN registers
17
18Example:
19
20 pcie@3400000 {
21 compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
22 reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */
23 0x40 0x00000000 0x0 0x00002000>; /* configuration space */
24 reg-names = "regs", "config";
25 interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
26 interrupt-names = "intr";
27 fsl,pcie-scfg = <&scfg 0>;
28 #address-cells = <3>;
29 #size-cells = <2>;
30 device_type = "pci";
31 num-lanes = <4>;
32 bus-range = <0x0 0xff>;
33 ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */
34 0xc2000000 0x0 0x20000000 0x40 0x20000000 0x0 0x20000000 /* prefetchable memory */
35 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
36 #interrupt-cells = <1>;
37 interrupt-map-mask = <0 0 0 7>;
38 interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
39 <0000 0 0 2 &gic GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
40 <0000 0 0 3 &gic GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
41 <0000 0 0 4 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
42 };
diff --git a/MAINTAINERS b/MAINTAINERS
index a20df9bf8ab0..016e1ef1c16c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6983,6 +6983,16 @@ S: Maintained
6983F: Documentation/devicetree/bindings/pci/xgene-pci.txt 6983F: Documentation/devicetree/bindings/pci/xgene-pci.txt
6984F: drivers/pci/host/pci-xgene.c 6984F: drivers/pci/host/pci-xgene.c
6985 6985
6986PCI DRIVER FOR FREESCALE LAYERSCAPE
6987M: Minghuan Lian <minghuan.Lian@freescale.com>
6988M: Mingkai Hu <mingkai.hu@freescale.com>
6989M: Roy Zang <tie-fei.zang@freescale.com>
6990L: linuxppc-dev@lists.ozlabs.org
6991L: linux-pci@vger.kernel.org
6992L: linux-arm-kernel@lists.infradead.org
6993S: Maintained
6994F: drivers/pci/host/*layerscape*
6995
6986PCI DRIVER FOR IMX6 6996PCI DRIVER FOR IMX6
6987M: Richard Zhu <r65037@freescale.com> 6997M: Richard Zhu <r65037@freescale.com>
6988M: Lucas Stach <l.stach@pengutronix.de> 6998M: Lucas Stach <l.stach@pengutronix.de>
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 3dc25fad490c..67e2cc5a0bd4 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -91,4 +91,12 @@ config PCI_XGENE
91 There are 5 internal PCIe ports available. Each port is GEN3 capable 91 There are 5 internal PCIe ports available. Each port is GEN3 capable
92 and have varied lanes from x1 to x8. 92 and have varied lanes from x1 to x8.
93 93
94config PCI_LAYERSCAPE
95 bool "Freescale Layerscape PCIe controller"
96 depends on OF && ARM
97 select PCIE_DW
98 select MFD_SYSCON
99 help
100 Say Y here if you want PCIe controller support on Layerscape SoCs.
101
94endmenu 102endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 26b3461d68d7..44c26998027f 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
11obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o 11obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
12obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o 12obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
13obj-$(CONFIG_PCI_XGENE) += pci-xgene.o 13obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
14obj-$(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 000000000000..6697b1a4d4fa
--- /dev/null
+++ b/drivers/pci/host/pci-layerscape.c
@@ -0,0 +1,179 @@
1/*
2 * PCIe host controller driver for Freescale Layerscape SoCs
3 *
4 * Copyright (C) 2014 Freescale Semiconductor.
5 *
6 * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/delay.h>
15#include <linux/interrupt.h>
16#include <linux/module.h>
17#include <linux/of_pci.h>
18#include <linux/of_platform.h>
19#include <linux/of_irq.h>
20#include <linux/of_address.h>
21#include <linux/pci.h>
22#include <linux/platform_device.h>
23#include <linux/resource.h>
24#include <linux/mfd/syscon.h>
25#include <linux/regmap.h>
26
27#include "pcie-designware.h"
28
29/* PEX1/2 Misc Ports Status Register */
30#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
31#define LTSSM_STATE_SHIFT 20
32#define LTSSM_STATE_MASK 0x3f
33#define LTSSM_PCIE_L0 0x11 /* L0 state */
34
35/* Symbol Timer Register and Filter Mask Register 1 */
36#define PCIE_STRFMR1 0x71c
37
38struct ls_pcie {
39 struct list_head node;
40 struct device *dev;
41 struct pci_bus *bus;
42 void __iomem *dbi;
43 struct regmap *scfg;
44 struct pcie_port pp;
45 int index;
46 int msi_irq;
47};
48
49#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
50
51static int ls_pcie_link_up(struct pcie_port *pp)
52{
53 u32 state;
54 struct ls_pcie *pcie = to_ls_pcie(pp);
55
56 regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
57 state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
58
59 if (state < LTSSM_PCIE_L0)
60 return 0;
61
62 return 1;
63}
64
65static void ls_pcie_host_init(struct pcie_port *pp)
66{
67 struct ls_pcie *pcie = to_ls_pcie(pp);
68 int count = 0;
69 u32 val;
70
71 dw_pcie_setup_rc(pp);
72
73 while (!ls_pcie_link_up(pp)) {
74 usleep_range(100, 1000);
75 count++;
76 if (count >= 200) {
77 dev_err(pp->dev, "phy link never came up\n");
78 return;
79 }
80 }
81
82 /*
83 * LS1021A Workaround for internal TKT228622
84 * to fix the INTx hang issue
85 */
86 val = ioread32(pcie->dbi + PCIE_STRFMR1);
87 val &= 0xffff;
88 iowrite32(val, pcie->dbi + PCIE_STRFMR1);
89}
90
91static struct pcie_host_ops ls_pcie_host_ops = {
92 .link_up = ls_pcie_link_up,
93 .host_init = ls_pcie_host_init,
94};
95
96static int ls_add_pcie_port(struct ls_pcie *pcie)
97{
98 struct pcie_port *pp;
99 int ret;
100
101 pp = &pcie->pp;
102 pp->dev = pcie->dev;
103 pp->dbi_base = pcie->dbi;
104 pp->root_bus_nr = -1;
105 pp->ops = &ls_pcie_host_ops;
106
107 ret = dw_pcie_host_init(pp);
108 if (ret) {
109 dev_err(pp->dev, "failed to initialize host\n");
110 return ret;
111 }
112
113 return 0;
114}
115
116static int __init ls_pcie_probe(struct platform_device *pdev)
117{
118 struct ls_pcie *pcie;
119 struct resource *dbi_base;
120 u32 index[2];
121 int ret;
122
123 pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
124 if (!pcie)
125 return -ENOMEM;
126
127 pcie->dev = &pdev->dev;
128
129 dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
130 if (!dbi_base) {
131 dev_err(&pdev->dev, "missing *regs* space\n");
132 return -ENODEV;
133 }
134
135 pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base);
136 if (IS_ERR(pcie->dbi))
137 return PTR_ERR(pcie->dbi);
138
139 pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
140 "fsl,pcie-scfg");
141 if (IS_ERR(pcie->scfg)) {
142 dev_err(&pdev->dev, "No syscfg phandle specified\n");
143 return PTR_ERR(pcie->scfg);
144 }
145
146 ret = of_property_read_u32_array(pdev->dev.of_node,
147 "fsl,pcie-scfg", index, 2);
148 if (ret)
149 return ret;
150 pcie->index = index[1];
151
152 ret = ls_add_pcie_port(pcie);
153 if (ret < 0)
154 return ret;
155
156 platform_set_drvdata(pdev, pcie);
157
158 return 0;
159}
160
161static const struct of_device_id ls_pcie_of_match[] = {
162 { .compatible = "fsl,ls1021a-pcie" },
163 { },
164};
165MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
166
167static struct platform_driver ls_pcie_driver = {
168 .driver = {
169 .name = "layerscape-pcie",
170 .owner = THIS_MODULE,
171 .of_match_table = ls_pcie_of_match,
172 },
173};
174
175module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
176
177MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>");
178MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver");
179MODULE_LICENSE("GPL v2");