diff options
author | Luka Perkov <luka@openwrt.org> | 2013-09-27 01:52:28 +0000 |
---|---|---|
committer | Luka Perkov <luka@openwrt.org> | 2013-09-27 01:52:28 +0000 |
commit | d0603d6615501216ba6c9cf28c03278cd201c55c (patch) | |
tree | e09a3c949729bd57dfffcccfd12b4de253616c3d /target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch | |
parent | a0848b5884403d5a2d001776216cbf3faf517537 (diff) | |
download | upstream-d0603d6615501216ba6c9cf28c03278cd201c55c.tar.gz upstream-d0603d6615501216ba6c9cf28c03278cd201c55c.tar.bz2 upstream-d0603d6615501216ba6c9cf28c03278cd201c55c.zip |
mvebu: drop 3.8 support
Signed-off-by: Luka Perkov <luka@openwrt.org>
SVN-Revision: 38225
Diffstat (limited to 'target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch')
-rw-r--r-- | target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch | 474 |
1 files changed, 0 insertions, 474 deletions
diff --git a/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch b/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch deleted file mode 100644 index aa4e1f426d..0000000000 --- a/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch +++ /dev/null @@ -1,474 +0,0 @@ -This driver implements the hw_pci operations needed by the core ARM -PCI code to setup PCI devices and get their corresponding IRQs, and -the pci_ops operations that are used by the PCI core to read/write the -configuration space of PCI devices. - -In addition, this driver enumerates the different PCIe slots, and for -those having a device plugged in, it allocates the necessary address -decoding windows, using the new armada_370_xp_alloc_pcie_window() -function from mach-mvebu/addr-map.c. - -Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> ---- - .../devicetree/bindings/pci/armada-370-xp-pcie.txt | 136 +++++++++ - arch/arm/mach-mvebu/Makefile | 1 + - arch/arm/mach-mvebu/pcie.c | 306 ++++++++++++++++++++ - 3 files changed, 443 insertions(+) - create mode 100644 Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt - create mode 100644 arch/arm/mach-mvebu/pcie.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt -@@ -0,0 +1,136 @@ -+* Marvell Armada 370/XP PCIe interfaces -+ -+Mandatory properties: -+- compatible: must be "marvell,armada-370-xp-pcie" -+- status: either "disabled" or "okay" -+- #address-cells, set to <1> -+- #size-cells, set to <1> -+- ranges: describes the association between the physical addresses of -+ the PCIe registers for each PCIe interface with "virtual" addresses -+ as seen by the sub-nodes. One entry per PCIe interface. Each entry -+ must have 3 values: the "virtual" address seen by the sub-nodes, the -+ real physical address of the PCIe registers, and the size. -+ -+In addition, the Device Tree node must have sub-nodes describing each -+PCIe interface, having the following mandatory properties: -+- reg: the address and size of the PCIe registers (translated -+ addresses according to the ranges property of the parent) -+- interrupts: the interrupt number of this PCIe interface -+- clocks: the clock associated to this PCIe interface -+- marvell,pcie-port: the physical PCIe port number -+- status: either "disabled" or "okay" -+ -+and the following optional properties: -+- marvell,pcie-lane: the physical PCIe lane number, for ports having -+ multiple lanes. If this property is not found, we assume that the -+ value is 0. -+ -+Example: -+ -+pcie-controller { -+ compatible = "marvell,armada-370-xp-pcie"; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0xd0040000 0x2000 /* port0x1_port0 */ -+ 0x2000 0xd0042000 0x2000 /* port2x1_port0 */ -+ 0x4000 0xd0044000 0x2000 /* port0x1_port1 */ -+ 0x8000 0xd0048000 0x2000 /* port0x1_port2 */ -+ 0xC000 0xd004C000 0x2000 /* port0x1_port3 */ -+ 0x10000 0xd0080000 0x2000 /* port1x1_port0 */ -+ 0x12000 0xd0082000 0x2000 /* port3x1_port0 */ -+ 0x14000 0xd0084000 0x2000 /* port1x1_port1 */ -+ 0x18000 0xd0088000 0x2000 /* port1x1_port2 */ -+ 0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>; -+ -+ pcie0.0@0xd0040000 { -+ reg = <0x0 0x2000>; -+ interrupts = <58>; -+ clocks = <&gateclk 5>; -+ marvell,pcie-port = <0>; -+ marvell,pcie-lane = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie0.1@0xd0044000 { -+ reg = <0x4000 0x2000>; -+ interrupts = <59>; -+ clocks = <&gateclk 5>; -+ marvell,pcie-port = <0>; -+ marvell,pcie-lane = <1>; -+ status = "disabled"; -+ }; -+ -+ pcie0.2@0xd0048000 { -+ reg = <0x8000 0x2000>; -+ interrupts = <60>; -+ clocks = <&gateclk 5>; -+ marvell,pcie-port = <0>; -+ marvell,pcie-lane = <2>; -+ status = "disabled"; -+ }; -+ -+ pcie0.3@0xd004C000 { -+ reg = <0xC000 0x2000>; -+ interrupts = <61>; -+ clocks = <&gateclk 5>; -+ marvell,pcie-port = <0>; -+ marvell,pcie-lane = <3>; -+ status = "disabled"; -+ }; -+ -+ pcie1.0@0xd0040000 { -+ reg = <0x10000 0x2000>; -+ interrupts = <62>; -+ clocks = <&gateclk 6>; -+ marvell,pcie-port = <1>; -+ marvell,pcie-lane = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie1.1@0xd0044000 { -+ reg = <0x14000 0x2000>; -+ interrupts = <63>; -+ clocks = <&gateclk 6>; -+ marvell,pcie-port = <1>; -+ marvell,pcie-lane = <1>; -+ status = "disabled"; -+ }; -+ -+ pcie1.2@0xd0048000 { -+ reg = <0x18000 0x2000>; -+ interrupts = <64>; -+ clocks = <&gateclk 6>; -+ marvell,pcie-port = <1>; -+ marvell,pcie-lane = <2>; -+ status = "disabled"; -+ }; -+ -+ pcie1.3@0xd004C000 { -+ reg = <0x1C000 0x2000>; -+ interrupts = <65>; -+ clocks = <&gateclk 6>; -+ marvell,pcie-port = <1>; -+ marvell,pcie-lane = <3>; -+ status = "disabled"; -+ }; -+ -+ pcie2@0xd0042000 { -+ reg = <0x2000 0x2000>; -+ interrupts = <99>; -+ clocks = <&gateclk 7>; -+ marvell,pcie-port = <2>; -+ marvell,pcie-lane = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie3@0xd0082000 { -+ reg = <0x12000 0x2000>; -+ interrupts = <103>; -+ clocks = <&gateclk 8>; -+ marvell,pcie-port = <3>; -+ marvell,pcie-lane = <0>; -+ status = "disabled"; -+ }; -+}; -+ ---- a/arch/arm/mach-mvebu/Makefile -+++ b/arch/arm/mach-mvebu/Makefile -@@ -7,3 +7,4 @@ obj-y += system-controller.o - obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o - obj-$(CONFIG_SMP) += platsmp.o headsmp.o - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -+obj-$(CONFIG_PCI) += pcie.o ---- /dev/null -+++ b/arch/arm/mach-mvebu/pcie.c -@@ -0,0 +1,306 @@ -+/* -+ * PCIe driver for Marvell Armada 370 and Armada XP SoCs -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/pci.h> -+#include <linux/clk.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/platform_device.h> -+#include <linux/of_address.h> -+#include <linux/of_pci.h> -+#include <linux/of_irq.h> -+#include <linux/of_platform.h> -+#include <plat/pcie.h> -+#include "common.h" -+ -+struct pcie_port { -+ u8 root_bus_nr; -+ void __iomem *base; -+ spinlock_t conf_lock; -+ int irq; -+ struct resource res; -+ int haslink; -+ u32 port; -+ u32 lane; -+ struct clk *clk; -+}; -+ -+static struct pcie_port *pcie_ports; -+ -+static int pcie_valid_config(struct pcie_port *pp, int bus, int dev) -+{ -+ /* -+ * Don't go out when trying to access -- -+ * 1. nonexisting device on local bus -+ * 2. where there's no device connected (no link) -+ */ -+ if (bus == pp->root_bus_nr && dev == 0) -+ return 1; -+ -+ if (!orion_pcie_link_up(pp->base)) -+ return 0; -+ -+ if (bus == pp->root_bus_nr && dev != 1) -+ return 0; -+ -+ return 1; -+} -+ -+/* -+ * PCIe config cycles are done by programming the PCIE_CONF_ADDR register -+ * and then reading the PCIE_CONF_DATA register. Need to make sure these -+ * transactions are atomic. -+ */ -+static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, -+ int size, u32 *val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct pcie_port *pp = sys->private_data; -+ unsigned long flags; -+ int ret; -+ -+ if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) { -+ *val = 0xffffffff; -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ } -+ -+ spin_lock_irqsave(&pp->conf_lock, flags); -+ ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val); -+ spin_unlock_irqrestore(&pp->conf_lock, flags); -+ -+ return ret; -+} -+ -+static int pcie_wr_conf(struct pci_bus *bus, u32 devfn, -+ int where, int size, u32 val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct pcie_port *pp = sys->private_data; -+ unsigned long flags; -+ int ret; -+ -+ if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ spin_lock_irqsave(&pp->conf_lock, flags); -+ ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val); -+ spin_unlock_irqrestore(&pp->conf_lock, flags); -+ -+ return ret; -+} -+ -+static struct pci_ops pcie_ops = { -+ .read = pcie_rd_conf, -+ .write = pcie_wr_conf, -+}; -+ -+/* -+ * Returns 0 when the device could not be initialized, 1 when -+ * initialization is successful -+ */ -+static int __init armada_370_xp_pcie_setup(int nr, struct pci_sys_data *sys) -+{ -+ struct pcie_port *port = &pcie_ports[nr]; -+ unsigned long membase, iobase; -+ int ret; -+ -+ if (!port->haslink) -+ return 0; -+ -+ sys->private_data = port; -+ port->root_bus_nr = sys->busnr; -+ spin_lock_init(&port->conf_lock); -+ -+ ret = armada_370_xp_alloc_pcie_window(port->port, port->lane, -+ IORESOURCE_MEM, SZ_64M, &membase); -+ if (ret) { -+ pr_err("PCIe%d.%d: Cannot get memory window, device disabled\n", -+ port->port, port->lane); -+ return 0; -+ } -+ -+ ret = armada_370_xp_alloc_pcie_window(port->port, port->lane, -+ IORESOURCE_IO, SZ_64K, &iobase); -+ if (ret) { -+ pr_err("PCIe%d.%d: Cannot get I/O window, device disabled\n", -+ port->port, port->lane); -+ armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); -+ return 0; -+ } -+ -+ port->res.name = kasprintf(GFP_KERNEL, "PCIe %d.%d MEM", -+ port->port, port->lane); -+ if (!port->res.name) { -+ armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K); -+ armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); -+ return 0; -+ } -+ -+ port->res.start = membase; -+ port->res.end = membase + SZ_32M - 1; -+ port->res.flags = IORESOURCE_MEM; -+ -+ pci_ioremap_io(SZ_64K * sys->busnr, iobase); -+ -+ if (request_resource(&iomem_resource, &port->res)) { -+ pr_err("PCIe%d.%d: Cannot request memory resource\n", -+ port->port, port->lane); -+ kfree(port->res.name); -+ armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K); -+ armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); -+ return 0; -+ } -+ -+ pci_add_resource_offset(&sys->resources, &port->res, sys->mem_offset); -+ -+ orion_pcie_set_local_bus_nr(port->base, sys->busnr); -+ orion_pcie_setup(port->base); -+ -+ return 1; -+} -+ -+static void rc_pci_fixup(struct pci_dev *dev) -+{ -+ /* -+ * Prevent enumeration of root complex. -+ */ -+ if (dev->bus->parent == NULL && dev->devfn == 0) { -+ int i; -+ -+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { -+ dev->resource[i].start = 0; -+ dev->resource[i].end = 0; -+ dev->resource[i].flags = 0; -+ } -+ } -+} -+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); -+ -+static int __init armada_370_xp_pcie_map_irq(const struct pci_dev *dev, u8 slot, -+ u8 pin) -+{ -+ struct pci_sys_data *sys = dev->sysdata; -+ struct pcie_port *port = sys->private_data; -+ -+ return port->irq; -+} -+ -+static struct hw_pci armada_370_xp_pci __initdata = { -+ .setup = armada_370_xp_pcie_setup, -+ .map_irq = armada_370_xp_pcie_map_irq, -+ .ops = &pcie_ops, -+}; -+ -+static int __init armada_370_xp_pcie_probe(struct platform_device *pdev) -+{ -+ struct device_node *child; -+ int nports, i; -+ -+ nports = 0; -+ for_each_child_of_node(pdev->dev.of_node, child) { -+ if (!of_device_is_available(child)) -+ continue; -+ nports++; -+ } -+ -+ pcie_ports = devm_kzalloc(&pdev->dev, nports * sizeof(*pcie_ports), -+ GFP_KERNEL); -+ if (!pcie_ports) -+ return -ENOMEM; -+ -+ i = 0; -+ for_each_child_of_node(pdev->dev.of_node, child) { -+ struct pcie_port *port = &pcie_ports[i]; -+ -+ if (!of_device_is_available(child)) -+ continue; -+ -+ if (of_property_read_u32(child, "marvell,pcie-port", -+ &port->port)) -+ continue; -+ -+ if (of_property_read_u32(child, "marvell,pcie-lane", -+ &port->lane)) -+ port->lane = 0; -+ -+ port->base = of_iomap(child, 0); -+ if (!port->base) { -+ dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", -+ port->port, port->lane); -+ continue; -+ } -+ -+ if (orion_pcie_link_up(port->base)) { -+ port->haslink = 1; -+ dev_info(&pdev->dev, "PCIe%d.%d: link up\n", -+ port->port, port->lane); -+ } else { -+ port->haslink = 0; -+ dev_info(&pdev->dev, "PCIe%d.%d: link down\n", -+ port->port, port->lane); -+ iounmap(port->base); -+ continue; -+ } -+ -+ port->irq = irq_of_parse_and_map(child, 0); -+ if (port->irq == 0) { -+ dev_err(&pdev->dev, "PCIe%d.%d: cannot parse and map IRQ\n", -+ port->port, port->lane); -+ iounmap(port->base); -+ port->haslink = 0; -+ continue; -+ } -+ -+ port->clk = of_clk_get_by_name(child, NULL); -+ if (!port->clk) { -+ dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", -+ port->port, port->lane); -+ irq_dispose_mapping(port->irq); -+ iounmap(port->base); -+ port->haslink = 0; -+ continue; -+ } -+ -+ clk_prepare_enable(port->clk); -+ -+ i++; -+ } -+ -+ armada_370_xp_pci.nr_controllers = nports; -+ pci_common_init(&armada_370_xp_pci); -+ -+ return 0; -+} -+ -+static const struct of_device_id armada_370_xp_pcie_of_match_table[] = { -+ { .compatible = "marvell,armada-370-xp-pcie", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, armada_370_xp_pcie_of_match_table); -+ -+static struct platform_driver armada_370_xp_pcie_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "armada-370-xp-pcie", -+ .of_match_table = -+ of_match_ptr(armada_370_xp_pcie_of_match_table), -+ }, -+}; -+ -+static int armada_370_xp_pcie_init(void) -+{ -+ return platform_driver_probe(&armada_370_xp_pcie_driver, -+ armada_370_xp_pcie_probe); -+} -+ -+subsys_initcall(armada_370_xp_pcie_init); -+ -+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); -+MODULE_DESCRIPTION("Marvell Armada 370/XP PCIe driver"); -+MODULE_LICENSE("GPL"); |