PCIe support for the Armada 370 and Armada XP SoCs
Subsystems (11)
v7 cover PCIe support for the Armada 370 and Armada XP SoCs
Hello,
This series of patches introduces PCIe support for the Marvell Armada 370 and Armada XP. In the future, we plan to extend the driver to cover Kirkwood platforms, and possibly other Marvell EBU platforms as well.
As we are approaching 3.10, I would now like to get formal Acked-by, or disagreements from the following maintainers/developers :
* Grant Likely, as the OF maintainer, for patches 1, 2 and 3
[PATCH v5 01/17] of/pci: Provide support for parsing PCI DT ranges [PATCH v5 02/17] of/pci: Add of_pci_get_devfn() function [PATCH v5 03/17] of/pci: Add of_pci_parse_bus_range() function
* Bjorn Helgaas, as the PCI maintainer, for patches 4 and 8
[PATCH v5 04/17] pci: infrastructure to add drivers in drivers/pci/host [PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
* Russell King, as the ARM maintainer, for patch 5
[PATCH v5 05/17] arm: pci: add a align_resource hook
* Arnd Bergmann, Mitch Bradley and Jason Gunthorpe, for patch 8 (the PCIe driver itself), and specifically the Device Tree binding.
[PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
This patch set depends on:
* The arm-soc/mvebu/cleanup branch in Arnd and Olof arm-soc tree
* [PATCH v3 for 3.10] Introduce a Marvell EBU MBus driver
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/156883.html
For easier testing, the code has been pushed to:
git://github.com/MISL-EBU-System-SW/mainline-public.git marvell-pcie-v7
This PATCHv7 follows:
* PATCHv6, sent on March, 26st 2013
* PATCHv5, sent on March, 21st 2013
* PATCHv4, sent on March, 8th 2013
* PATCHv3, sent on February, 12th 2013
* PATCHv2, sent on January, 28th 2013
* RFCv1, sent on December, 7th 2012
Changes between v6 and v7:
* Use assigned-addresses in the DT subnodes for the MMIO PCIe registers, in order to align with what Thierry is doing on the Tegra PCIe driver.
* Added empty 'ranges;' properties in the subnodes, as requested by Arnd. Note that due to this, it is not possible to remove the #address-cells and #size-cells properties from the subnodes, as Jason Gunthorpe requested, otherwise the DT compiler complains with:
Warning (ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #address-cells (2) differs from /soc/pcie-controller (3)
Warning (ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #size-cells (1) differs from /soc/pcie-controller (2)
* Use the new RFCv3 patch from Andrew Murray for 'of/pci: Provide support for parsing PCI DT ranges property'.
* Updated the DT binding documentation accordingly.
Changes between v5 and v6:
* Use pci_create_root_bus() + pci_scan_child_bus() instead of pci_scan_root_bus(). This is needed to be able to add MSI support later on. Moreover Thierry Reding suggested that pci_scan_root_bus() "does a pci_bus_add_devices(), which is called again in pci_common_init() in the ARM code". Thanks Thierry for pointing out this issue.
Changes between v4 and v5:
* Rebased on top of 3.9-rc2 + the new mvebu-mbus driver (v3).
* Changed the names of the PCI DT sub-nodes to match the OF
specifications: they should be named pcie at DD,FF where DD is the device number and FF the function number. Requested by Mitch Bradley.
* Add the device_type = "pci" property at the pcie-controller level. Requested by Mitch Bradley.
* Drop patch 'of/pci: Add of_pci_get_bus() function' because it wasn't actually used in the rest of the patch series.
* Updated the patch 'of/pci: Provide support for parsing PCI DT ranges property' to use the latest version proposed by Andrew Murray on the devicetree-discuss@ mailing list.
Changes between v3 and v4:
* Rebased on top of 3.9-rc1.
* Drop patch "ARM: pci: Allow passing per-controller private data" because it was merged in 3.9.
* Drop patch "lib: devres: don't enclose pcim_*() functions in CONFIG_HAS_IOPORT", because it was merged in 3.9.
* Added CONFIG_PCI_MVEBU=y in mvebu_defconfig, so that the right PCI host controller driver is automatically enabled.
* Instead of using the DT 'ranges' property to encode the PCIe register ranges, use a 'reg' property on the main PCIe controller DT node together with a 'reg-names' property. Suggested by Jason Gunthorpe.
* Don't select PCI_SW_HOST_BRIDGE and PCI_SW_PCI_PCI_BRIDGE, they don't exist anymore. Reported by Bjorn Helgaas.
* Added support for the Armada XP GP board.
* Fix the 'ranges' property so that the memory range is an identity map between CPU addresses and bus addresses. Suggested by Arnd Bergmann.
* Changed the 'ranges' property to have the I/O region after the memory region.
* Use the new mvebu-mbus driver API to create/remove address decoding windows when needed. This remove the need to include <mach/addr-map.h>. Requested by Arnd Bergmann.
* Include directly into the driver the few common PCIe functions we were using from arch/arm/plat-orion/pcie.c. This allows to remove the inclusion of <plat/pcie.h>. Requested by Arnd Bergmann.
* Directly set up the address decoding windows when the memory base/limit and I/O base/limit are configured in the PCI-to-PCI bridge instead of relying on the memory and I/O accesses being enabled in the PCI_COMMAND register. Suggested by Bjorn Helgaas.
* Added some comments on top of the calculations of the I/O base/limit and memory base/limit. Suggested by Arnd Bergmann.
* Changed a bit the way the "realio" resource is created, from suggestions given by Arnd Bergmann.
* Updated the Device Tree binding documentation. Reported by Jason Gunthorpe.
* Instead of using "marvell,armada-370-xp-pcie" as the DT compatible string, use two separate compatible strings:
"marvell,armada-370-pcie" and "marvell,armada-xp-pcie". For now, the driver does the same thing for both.
Changes between v2 and v3:
* Use of_irq_map_pci() instead of of_irq_map_raw(), as suggested by Andrew Murray. In order to do this, we moved the interrupt-map and interrupt-map-mask DT properties from the main PCIe controller node to the DT subnodes representing each PCIe interface.
* Remove the usage of the emulated host bridge.
* Move the emulated PCI-to-PCI bridge code into the Marvell PCI driver itself, in order to allow a tighter integration. Suggested by Bjorn Helgaas and Jason Gunthorpe.
* Make the allocation of address decoding windows dynamic: it's when memory accesses or I/O accesses are enabled at the PCI-to-PCI bridge level that we allocate and setup the corresponding address decoding window. Requested by Bjorn Helgaas.
* Fixed the implementation of I/O accesses to use I/O addresses that fall within the normal IO_SPACE_LIMIT. This required using the "remap" functionality of address decoding windows, and therefore some changes in the address decoding window allocator. Follows a long discussion about I/O accesses.
* Set up a correct bus number in the configuration of the PCIe interfaces so that we don't have to fake bus numbers anymore. Requested by Jason Gunthorpe.
* Fix the of_pci_get_devfn() implementation according to Stephen Warren's comment.
* Use CFLAGS_ instead of ccflags to add the mach-mvebu and plat-orion include paths when building the pci-mvebu driver. This ensures that the include paths are only added when building this specific driver. Requested by Stephen Warren.
* Fix the ->resource_align() to only apply on bus 0 (the one on which the emulated PCI-to-PCI bridges sit), and to request an alignment on the size of the window (and not only 64 KB for I/O windows and 1 MB for memory windows).
* Clarified the commit log of "clk: mvebu: create parent-child relation for PCIe clocks on Armada 370"
Thanks,
Thomas
Andrew Murray (1):
of/pci: Provide support for parsing PCI DT ranges property
Thierry Reding (2):
of/pci: Add of_pci_get_devfn() function
of/pci: Add of_pci_parse_bus_range() function
Thomas Petazzoni (14):
pci: infrastructure to add drivers in drivers/pci/host
arm: pci: add a align_resource hook
clk: mvebu: create parent-child relation for PCIe clocks on Armada
370
clk: mvebu: add more PCIe clocks for Armada XP
pci: PCIe driver for Marvell Armada 370/XP systems
arm: mvebu: PCIe support is now available on mvebu
arm: mvebu: add PCIe Device Tree informations for Armada 370
arm: mvebu: add PCIe Device Tree informations for Armada XP
arm: mvebu: PCIe Device Tree informations for OpenBlocks AX3-4
arm: mvebu: PCIe Device Tree informations for Armada XP DB
arm: mvebu: PCIe Device Tree informations for Armada 370 Mirabox
arm: mvebu: PCIe Device Tree informations for Armada 370 DB
arm: mvebu: PCIe Device Tree informations for Armada XP GP
arm: mvebu: update defconfig with PCI and USB support
.../devicetree/bindings/pci/mvebu-pci.txt | 220 +++++ arch/arm/boot/dts/armada-370-db.dts | 17 + arch/arm/boot/dts/armada-370-mirabox.dts | 16 + arch/arm/boot/dts/armada-370.dtsi | 51 ++ arch/arm/boot/dts/armada-xp-db.dts | 33 + arch/arm/boot/dts/armada-xp-gp.dts | 21 + arch/arm/boot/dts/armada-xp-mv78230.dtsi | 104 +++ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 122 +++ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 188 ++++ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 9 + arch/arm/configs/mvebu_defconfig | 3 + arch/arm/include/asm/mach/pci.h | 11 + arch/arm/kernel/bios32.c | 6 + arch/arm/mach-mvebu/Kconfig | 2 + arch/microblaze/pci/pci-common.c | 110 +-- arch/mips/pci/pci.c | 50 +- arch/powerpc/kernel/pci-common.c | 99 +-- drivers/clk/mvebu/clk-gating-ctrl.c | 18 +- drivers/of/address.c | 63 ++ drivers/of/of_pci.c | 59 +- drivers/pci/Kconfig | 2 + drivers/pci/Makefile | 3 + drivers/pci/host/Kconfig | 8 + drivers/pci/host/Makefile | 4 + drivers/pci/host/pci-mvebu.c | 927 ++++++++++++++++++++ include/linux/of_address.h | 42 + include/linux/of_pci.h | 2 + 27 files changed, 2009 insertions(+), 181 deletions(-) create mode 100644 Documentation/devicetree/bindings/pci/mvebu-pci.txt create mode 100644 drivers/pci/host/Kconfig create mode 100644 drivers/pci/host/Makefile create mode 100644 drivers/pci/host/pci-mvebu.c
Signature · 1 line
1.7.9.5
PATCH v7 1/17 of/pci: Provide support for parsing PCI DT ranges property
From: Andrew Murray <[email protected]>
This patch factors out common implementation patterns to reduce overall kernel code and provide a means for host bridge drivers to directly obtain struct resources from the DT's ranges property without relying on architecture specific DT handling. This will make it easier to write archiecture independent host bridge drivers and mitigate against further duplication of DT parsing code.
This patch can be used in the following way:
struct of_pci_range_parser parser;
struct of_pci_range range;
if (of_pci_range_parser(&parser, np))
; //no ranges property
for_each_of_pci_range(&parser, &range) {
/*
directly access properties of the address range, e.g.:
range.pci_space, range.pci_addr, range.cpu_addr,
range.size, range.flags
alternatively obtain a struct resource, e.g.:
struct resource res;
of_pci_range_to_resource(&range, np, &res);
*/
}Additionally the implementation takes care of adjacent ranges and merges them into a single range (as was the case with powerpc and microblaze).
The modifications to microblaze, mips and powerpc have not been tested.
--- arch/microblaze/pci/pci-common.c | 110 ++++++++++++++------------------------ arch/mips/pci/pci.c | 50 ++++++----------- arch/powerpc/kernel/pci-common.c | 99 ++++++++++++---------------------- drivers/of/address.c | 63 ++++++++++++++++++++++ include/linux/of_address.h | 42 +++++++++++++++ 5 files changed, 194 insertions(+), 170 deletions(-)
arch/microblaze/pci/pci-common.c +39 -71
@@ -658,67 +658,43 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,void pci_process_bridge_OF_ranges (struct pci_controller *hose,struct device_node *dev,int primary) { -const u32 *ranges; -int rlen; -int pna =of_n_addr_cells (dev); -int np = pna +5 ;int memno =0 , isa_hole =-1 ; -u32 pci_space; -unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;unsigned long long isa_mb =0 ;struct resource *res; +struct of_pci_range range; +struct of_pci_range_parser parser; +u32 res_type;pr_info ("PCI host bridge %s %s ranges:\n" , dev->full_name, primary ?"(primary)" :"" ); -/* Get ranges property */ - ranges =of_get_property (dev,"ranges" , &rlen); -if (ranges ==NULL ) +/* Check for ranges property */ +if (of_pci_range_parser (&parser, dev))return ; -/* Parse it */ pr_debug ("Parsing ranges property...\n" ); -while ((rlen -= np *4 ) >=0 ) { +for_each_of_pci_range (&parser, &range) {/* Read next ranges element */ - pci_space = ranges[0 ]; - pci_addr =of_read_number (ranges +1 ,2 ); - cpu_addr =of_translate_address (dev, ranges +3 ); - size =of_read_number (ranges + pna +3 ,2 ); - -pr_debug ("pci_space: 0x%08x pci_addr:0x%016llx " , - pci_space, pci_addr); -pr_debug ("cpu_addr:0x%016llx size:0x%016llx\n" , - cpu_addr, size); - - ranges += np; +pr_debug ("pci_space: 0x%08x pci_addr: 0x%016llx " , + range.pci_space, range.pci_addr); +pr_debug ("cpu_addr: 0x%016llx size: 0x%016llx\n" , + range.cpu_addr, range.size);/* If we failed translation or got a zero-sized region * (some FW try to feed us with non sensical zero sized regions * such as power3 which look like some kind of attempt * at exposing the VGA memory hole) */ -if (cpu_addr ==OF_BAD_ADDR || size ==0 ) +if (range.cpu_addr ==OF_BAD_ADDR || range.size ==0 )continue ; -/* Now consume following elements while they are contiguous */ -for (; rlen >= np *sizeof (u32); - ranges += np, rlen -= np *4 ) { -if (ranges[0 ] != pci_space) -break ; - pci_next =of_read_number (ranges +1 ,2 ); - cpu_next =of_translate_address (dev, ranges +3 ); -if (pci_next != pci_addr + size || - cpu_next != cpu_addr + size) -break ; - size +=of_read_number (ranges + pna +3 ,2 ); - } -/* Act based on address space type */ res =NULL ; -switch ((pci_space >>24 ) &0x3 ) { -case 1 :/* PCI IO space */ + res_type = range.flags &IORESOURCE_TYPE_BITS ; +if (res_type ==IORESOURCE_IO ) {pr_info (" IO 0x%016llx..0x%016llx -> 0x%016llx\n" , - cpu_addr, cpu_addr + size -1 , pci_addr); + range.cpu_addr, range.cpu_addr + range.size -1 , + range.pci_addr);/* We support only one IO range */ if (hose->pci_io_size) {
@@ -726,11 +702,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,continue ; }/* On 32 bits, limit I/O space to 16MB */ -if (size >0x01000000 ) - size =0x01000000 ; +if (range.size >0x01000000 ) + range.size =0x01000000 ;/* 32 bits needs to map IOs here */ - hose->io_base_virt =ioremap (cpu_addr, size); + hose->io_base_virt =ioremap (range.cpu_addr, + range.size);/* Expect trouble if pci_addr is not 0 */ if (primary)
@@ -739,19 +716,18 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,/* pci_io_size and io_base_phys always represent IO * space starting at 0 so we factor in pci_addr */ - hose->pci_io_size = pci_addr + size; - hose->io_base_phys = cpu_addr - pci_addr; + hose->pci_io_size = range.pci_addr + range.size; + hose->io_base_phys = range.cpu_addr - range.pci_addr;/* Build resource */ res = &hose->io_resource; - res->flags =IORESOURCE_IO ; - res->start = pci_addr; -break ; -case 2 :/* PCI Memory space */ -case 3 :/* PCI 64 bits Memory space */ + range.cpu_addr = range.pci_addr; + }else if (res_type ==IORESOURCE_MEM ) {pr_info (" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n" , - cpu_addr, cpu_addr + size -1 , pci_addr, - (pci_space &0x40000000 ) ?"Prefetch" :"" ); + range.cpu_addr, range.cpu_addr + range.size -1 , + range.pci_addr, + (range.pci_space &0x40000000 ) ? +"Prefetch" :"" );/* We support only 3 memory ranges */ if (memno >=3 ) {
@@ -759,13 +735,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,continue ; }/* Handles ISA memory hole space here */ -if (pci_addr ==0 ) { +if (range.pci_addr ==0 ) { isa_mb = cpu_addr; isa_hole = memno;if (primary || isa_mem_base ==0 ) - isa_mem_base = cpu_addr; - hose->isa_mem_phys = cpu_addr; - hose->isa_mem_size = size; + isa_mem_base = range.cpu_addr; + hose->isa_mem_phys = range.cpu_addr; + hose->isa_mem_size = range.size; }/* We get the PCI/Mem offset from the first range or
@@ -773,30 +749,22 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,* hole. If they don't match, bugger. */ if (memno ==0 || - (isa_hole >=0 && pci_addr !=0 && + (isa_hole >=0 && range.pci_addr !=0 && hose->pci_mem_offset == isa_mb)) - hose->pci_mem_offset = cpu_addr - pci_addr; -else if (pci_addr !=0 && - hose->pci_mem_offset != cpu_addr - pci_addr) { + hose->pci_mem_offset = range.cpu_addr + - range.pci_addr; +else if (range.pci_addr !=0 && + hose->pci_mem_offset != range.cpu_addr + - range.pci_addr) {pr_info (" \\--> Skipped (offset mismatch) !\n" );continue ; }/* Build resource */ res = &hose->mem_resources[memno++]; - res->flags =IORESOURCE_MEM ; -if (pci_space &0x40000000 ) - res->flags |=IORESOURCE_PREFETCH ; - res->start = cpu_addr; -break ; - } -if (res !=NULL ) { - res->name = dev->full_name; - res->end = res->start + size -1 ; - res->parent =NULL ; - res->sibling =NULL ; - res->child =NULL ; } +if (res !=NULL ) +of_pci_range_to_resource (&range, dev, res); }/* If there's an ISA hole and the pci_mem_offset is -not- matching
arch/mips/pci/pci.c +16 -34
67 lines not on this page · raw message
arch/powerpc/kernel/pci-common.c +34 -65
169 lines not on this page · raw message
drivers/of/address.c +63 -0
69 lines not on this page · raw message
include/linux/of_address.h +42 -0
60 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v7 2/17 of/pci: Add of_pci_get_devfn() function
In reply to Thomas PetazzoniFrom: Thierry Reding <[email protected]>
This function can be used to parse the device and function number from a standard 5-cell PCI resource. PCI_SLOT() and PCI_FUNC() can be used on the returned value obtain the device and function numbers respectively.
--- drivers/of/of_pci.c | 34 +++++++++++++++++++++++++++++----- include/linux/of_pci.h | 1 + 2 files changed, 30 insertions(+), 5 deletions(-)
drivers/of/of_pci.c +29 -5
@@ -5,14 +5,15 @@#include <asm/prom.h> static inline int __of_pci_pci_compare (struct device_node *node, -unsigned int devfn) +unsigned int data) { -unsigned int size; -const __be32 *reg =of_get_property (node,"reg" , &size); +int devfn; -if (!reg || size <5 *sizeof (__be32)) + devfn =of_pci_get_devfn (node); +if (devfn <0 )return 0 ; -return ((be32_to_cpup (®[0 ]) >>8 ) &0xff ) == devfn; + +return devfn == data; } struct device_node *of_pci_find_child_device(struct device_node *parent,
@@ -40,3 +41,26 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,return NULL ; }EXPORT_SYMBOL_GPL (of_pci_find_child_device); + +/** +* of_pci_get_devfn() - Get device and function numbers for a device node +* @np: device node +* +* Parses a standard 5-cell PCI resource and returns an 8-bit value that can +* be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device +* and function numbers respectively. On error a negative error code is +* returned. +*/ +int of_pci_get_devfn (struct device_node *np) +{ +unsigned int size; +const __be32 *reg; + + reg =of_get_property (np,"reg" , &size); + +if (!reg || size <5 *sizeof (__be32)) +return -EINVAL ; + +return (be32_to_cpup (reg) >>8 ) &0xff ; +} +EXPORT_SYMBOL_GPL (of_pci_get_devfn);
include/linux/of_pci.h +1 -0
@@ -10,5 +10,6 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);struct device_node ;struct device_node *of_pci_find_child_device (struct device_node *parent,unsigned int devfn); +int of_pci_get_devfn (struct device_node *np);#endif
Signature · 1 line
1.7.9.5
PATCH v7 3/17 of/pci: Add of_pci_parse_bus_range() function
In reply to Thomas PetazzoniFrom: Thierry Reding <[email protected]>
This function can be used to parse a bus-range property as specified by device nodes representing PCI bridges.
--- drivers/of/of_pci.c | 25 +++++++++++++++++++++++++ include/linux/of_pci.h | 1 + 2 files changed, 26 insertions(+)
drivers/of/of_pci.c +25 -0
@@ -64,3 +64,28 @@ int of_pci_get_devfn(struct device_node *np)return (be32_to_cpup (reg) >>8 ) &0xff ; }EXPORT_SYMBOL_GPL (of_pci_get_devfn); + +/** +* of_pci_parse_bus_range() - parse the bus-range property of a PCI device +* @node: device node +* @res: address to a struct resource to return the bus-range +* +* Returns 0 on success or a negative error-code on failure. +*/ +int of_pci_parse_bus_range (struct device_node *node,struct resource *res) +{ +const __be32 *values; +int len; + + values =of_get_property (node,"bus-range" , &len); +if (!values || len <sizeof (*values) *2 ) +return -EINVAL ; + + res->name = node->name; + res->start =be32_to_cpup (values++); + res->end =be32_to_cpup (values); + res->flags =IORESOURCE_BUS ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (of_pci_parse_bus_range);
include/linux/of_pci.h +1 -0
@@ -11,5 +11,6 @@ struct device_node;struct device_node *of_pci_find_child_device (struct device_node *parent,unsigned int devfn);int of_pci_get_devfn (struct device_node *np); +int of_pci_parse_bus_range (struct device_node *node,struct resource *res);#endif
Signature · 1 line
1.7.9.5
PATCH v7 4/17 pci: infrastructure to add drivers in drivers/pci/host
In reply to Thomas PetazzoniAs agreed by the community, PCI host drivers will now be stored in drivers/pci/host. This commit adds this directory and the related Kconfig/Makefile changes to allow new drivers to be added in this directory.
--- drivers/pci/Kconfig | 2 ++ drivers/pci/Makefile | 3 +++ drivers/pci/host/Kconfig | 4 ++++ 3 files changed, 9 insertions(+) create mode 100644 drivers/pci/host/Kconfig
drivers/pci/Kconfig +2 -0
@@ -119,3 +119,5 @@ config PCI_IOAPIC config PCI_LABEL def_bool y if (DMI || ACPI) select NLS + +source "drivers/pci/host/Kconfig"
drivers/pci/Makefile +3 -0
@@ -67,3 +67,6 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_OF) += of.o ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG + +# PCI host controller drivers +obj-y += host/
drivers/pci/host/Kconfig new file +4 -0
@@ -0,0 +1,4 @@ +menu "PCI host controller drivers" + depends on PCI + +endmenu
Signature · 1 line
1.7.9.5
A message that is not in the archive (sent off-list or not yet received): CAAfodu2t4j4ZASzdaKV0QarffXRwMgkMESGy=dDq1oMfTANEeg@mail.gmail.com
PATCH v7 4/17 pci: infrastructure to add drivers in drivers/pci/host
Dear Neil Greatorex,
Quoted 2 lines · Neil Greatorex
Surely this patch should include the
drivers/pci/host/Makefileor it will not build?
Ah, correct. I'll fix that up in the v8. Thank you for noticing!
Best regards,
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Bjorn Helgaas
maintainerPATCH v7 4/17 pci: infrastructure to add drivers in drivers/pci/host
Quoted 8 lines · Thomas Petazzoni
Dear Neil Greatorex,
Quoted 2 lines · Neil Greatorex
Surely this patch should include the
drivers/pci/host/Makefileor it will not build?Ah, correct. I'll fix that up in the v8. Thank you for noticing!
With the fix, looks OK to me.
Bjorn
PATCH v7 5/17 arm: pci: add a align_resource hook
In reply to Thomas PetazzoniThe PCI specifications says that an I/O region must be aligned on a 4 KB boundary, and a memory region aligned on a 1 MB boundary.
However, the Marvell PCIe interfaces rely on address decoding windows (which allow to associate a range of physical addresses with a given device). For PCIe memory windows, those windows are defined with a 1 MB granularity (which matches the PCI specs), but PCIe I/O windows can only be defined with a 64 KB granularity, so they have to be 64 KB aligned. We therefore need to tell the PCI core about this special alignement requirement.
The PCI core already calls pcibios_align_resource() in the ARM PCI core, specifically for such purposes. So this patch extends the ARM PCI core so that it calls a ->align_resource() hook registered by the PCI driver, exactly like the existing ->map_irq() and ->swizzle() hooks.
A particular PCI driver can register a align_resource() hook, and do its own specific alignement, depending on the specific constraints of the underlying hardware.
--- arch/arm/include/asm/mach/pci.h | 11 +++++++++++ arch/arm/kernel/bios32.c | 6 ++++++ 2 files changed, 17 insertions(+)
arch/arm/include/asm/mach/pci.h +11 -0
@@ -30,6 +30,11 @@ struct hw_pci {void (*postinit)(void );u8 (*swizzle)(struct pci_dev *dev,u8 *pin);int (*map_irq)(const struct pci_dev *dev,u8 slot,u8 pin); +resource_size_t (*align_resource)(struct pci_dev *dev, +const struct resource *res, +resource_size_t start, +resource_size_t size, +resource_size_t align); };/*
@@ -51,6 +56,12 @@ struct pci_sys_data {u8 (*swizzle)(struct pci_dev *,u8 *);/* IRQ mapping */ int (*map_irq)(const struct pci_dev *,u8 ,u8 ); +/* Resource alignement requirements */ +resource_size_t (*align_resource)(struct pci_dev *dev, +const struct resource *res, +resource_size_t start, +resource_size_t size, +resource_size_t align);void *private_data;/* platform controller private data */ };
arch/arm/kernel/bios32.c +6 -0
@@ -462,6 +462,7 @@ static void pcibios_init_hw(struct hw_pci *hw, struct list_head *head) sys->busnr = busnr; sys->swizzle = hw->swizzle; sys->map_irq = hw->map_irq; + sys->align_resource = hw->align_resource;INIT_LIST_HEAD (&sys->resources);if (hw->private_data)
@@ -574,6 +575,8 @@ char * __init pcibios_setup(char *str)resource_size_t pcibios_align_resource (void *data,const struct resource *res,resource_size_t size,resource_size_t align) { +struct pci_dev *dev = data; +struct pci_sys_data *sys = dev->sysdata;resource_size_t start = res->start;if (res->flags &IORESOURCE_IO && start &0x300 )
@@ -581,6 +584,9 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, start = (start + align -1 ) & ~(align -1 ); +if (sys->align_resource) +return sys->align_resource (dev, res, start, size, align); +return start; }
Signature · 1 line
1.7.9.5
PATCH v7 6/17 clk: mvebu: create parent-child relation for PCIe clocks on Armada 370
In reply to Thomas PetazzoniThe Armada 370 has two gatable clocks for each PCIe interface, and we want both of them to be enabled. We therefore make one of the two clocks a child of the other, as we did for the sataX and sataXlnk clocks on Armada XP.
--- drivers/clk/mvebu/clk-gating-ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/mvebu/clk-gating-ctrl.c +2 -2
@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = { { "pex1_en", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 9 }, + { "pex0", "pex0_en", 5 }, + { "pex1", "pex1_en", 9 }, { "sata0", NULL, 15 }, { "sdio", NULL, 17 }, { "tdm", NULL, 25 },
Signature · 1 line
1.7.9.5
PATCH v7 6/17 clk: mvebu: create parent-child relation for PCIe clocks on Armada 370
Mike,
Could we have your opinion on this patch, and possibly a Acked-by to pass it through arm-soc?
Thanks!
Thomas
Quoted 26 lines · Thomas Petazzoni
The Armada 370 has two gatable clocks for each PCIe interface, and we want both of them to be enabled. We therefore make one of the two clocks a child of the other, as we did for the sataX and sataXlnk clocks on Armada XP.
Signed-off-by Thomas Petazzoni <[email protected]>Cc Mike Turquette <[email protected]>--- drivers/clk/mvebu/clk-gating-ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/clk/mvebu/clk-gating-ctrl.c +2
-2@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = { { "pex1_en", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 9 }, + { "pex0", "pex0_en", 5 }, + { "pex1", "pex1_en", 9 }, { "sata0", NULL, 15 }, { "sdio", NULL, 17 }, { "tdm", NULL, 25 },
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 6/17 clk: mvebu: create parent-child relation for PCIe clocks on Armada 370
In reply to Thomas PetazzoniQuoting Thomas Petazzoni (2013-03-27 07:40:23)
Quoted 7 lines
The Armada 370 has two gatable clocks for each PCIe interface, and we want both of them to be enabled. We therefore make one of the two clocks a child of the other, as we did for the sataX and sataXlnk clocks on Armada XP.
Signed-off-by Thomas Petazzoni <[email protected]>Cc Mike Turquette <[email protected]>
Quoted 21 lines
--- drivers/clk/mvebu/clk-gating-ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/clk/mvebu/clk-gating-ctrl.c +2
-2@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = { { "pex1_en", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 9 }, + { "pex0", "pex0_en", 5 }, + { "pex1", "pex1_en", 9 }, { "sata0", NULL, 15 }, { "sdio", NULL, 17 }, { "tdm", NULL, 25 },Signature · 1 line
1.7.9.5
PATCH v7 7/17 clk: mvebu: add more PCIe clocks for Armada XP
In reply to Thomas PetazzoniThe current revision of the datasheet only mentions the gatable clocks for the PCIe 0.0, 0.1, 0.2 and 0.3 interfaces, and forgot to mention the ones for the PCIe 1.0, 1.1, 1.2, 1.3, 2.0 and 3.0 interfaces. After confirmation with Marvell engineers, this patch adds the missing gatable clocks for those PCIe interfaces.
It also changes the name of the previously existing PCIe gatable clocks, in order to match the naming using the datasheets.
--- drivers/clk/mvebu/clk-gating-ctrl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/clk/mvebu/clk-gating-ctrl.c +10 -4
@@ -137,10 +137,14 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "ge2", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 6 }, - { "pex2", NULL, 7 }, - { "pex3", NULL, 8 }, + { "pex00", NULL, 5 }, + { "pex01", NULL, 6 }, + { "pex02", NULL, 7 }, + { "pex03", NULL, 8 }, + { "pex10", NULL, 9 }, + { "pex11", NULL, 10 }, + { "pex12", NULL, 11 }, + { "pex13", NULL, 12 }, { "bp", NULL, 13 }, { "sata0lnk", NULL, 14 }, { "sata0", "sata0lnk", 15 },
@@ -152,6 +156,8 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "xor0", NULL, 22 }, { "crypto", NULL, 23 }, { "tdm", NULL, 25 }, + { "pex20", NULL, 26 }, + { "pex30", NULL, 27 }, { "xor1", NULL, 28 }, { "sata1lnk", NULL, 29 }, { "sata1", "sata1lnk", 30 },
Signature · 1 line
1.7.9.5
PATCH v7 7/17 clk: mvebu: add more PCIe clocks for Armada XP
Mike,
Could we have your opinion on the below patch, and possibly an Acked-by to carry it through the arm-soc tree?
Thanks,
Thomas
Quoted 46 lines · Thomas Petazzoni
The current revision of the datasheet only mentions the gatable clocks for the PCIe 0.0, 0.1, 0.2 and 0.3 interfaces, and forgot to mention the ones for the PCIe 1.0, 1.1, 1.2, 1.3, 2.0 and 3.0 interfaces. After confirmation with Marvell engineers, this patch adds the missing gatable clocks for those PCIe interfaces.
It also changes the name of the previously existing PCIe gatable clocks, in order to match the naming using the datasheets.
Signed-off-by Thomas Petazzoni <[email protected]>--- drivers/clk/mvebu/clk-gating-ctrl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)drivers/clk/mvebu/clk-gating-ctrl.c +10
-4@@ -137,10 +137,14 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "ge2", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 6 }, - { "pex2", NULL, 7 }, - { "pex3", NULL, 8 }, + { "pex00", NULL, 5 }, + { "pex01", NULL, 6 }, + { "pex02", NULL, 7 }, + { "pex03", NULL, 8 }, + { "pex10", NULL, 9 }, + { "pex11", NULL, 10 }, + { "pex12", NULL, 11 }, + { "pex13", NULL, 12 }, { "bp", NULL, 13 }, { "sata0lnk", NULL, 14 }, { "sata0", "sata0lnk", 15 },@@ -152,6 +156,8 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "xor0", NULL, 22 }, { "crypto", NULL, 23 }, { "tdm", NULL, 25 }, + { "pex20", NULL, 26 }, + { "pex30", NULL, 27 }, { "xor1", NULL, 28 }, { "sata1lnk", NULL, 29 }, { "sata1", "sata1lnk", 30 },
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 7/17 clk: mvebu: add more PCIe clocks for Armada XP
In reply to Thomas PetazzoniQuoting Thomas Petazzoni (2013-03-27 07:40:24)
Quoted 10 lines
The current revision of the datasheet only mentions the gatable clocks for the PCIe 0.0, 0.1, 0.2 and 0.3 interfaces, and forgot to mention the ones for the PCIe 1.0, 1.1, 1.2, 1.3, 2.0 and 3.0 interfaces. After confirmation with Marvell engineers, this patch adds the missing gatable clocks for those PCIe interfaces.
It also changes the name of the previously existing PCIe gatable clocks, in order to match the naming using the datasheets.
Signed-off-by Thomas Petazzoni <[email protected]>
Quoted 44 lines
--- drivers/clk/mvebu/clk-gating-ctrl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)drivers/clk/mvebu/clk-gating-ctrl.c +10
-4@@ -137,10 +137,14 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "ge2", NULL, 2 }, { "ge1", NULL, 3 }, { "ge0", NULL, 4 }, - { "pex0", NULL, 5 }, - { "pex1", NULL, 6 }, - { "pex2", NULL, 7 }, - { "pex3", NULL, 8 }, + { "pex00", NULL, 5 }, + { "pex01", NULL, 6 }, + { "pex02", NULL, 7 }, + { "pex03", NULL, 8 }, + { "pex10", NULL, 9 }, + { "pex11", NULL, 10 }, + { "pex12", NULL, 11 }, + { "pex13", NULL, 12 }, { "bp", NULL, 13 }, { "sata0lnk", NULL, 14 }, { "sata0", "sata0lnk", 15 },@@ -152,6 +156,8 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = { { "xor0", NULL, 22 }, { "crypto", NULL, 23 }, { "tdm", NULL, 25 }, + { "pex20", NULL, 26 }, + { "pex30", NULL, 27 }, { "xor1", NULL, 28 }, { "sata1lnk", NULL, 29 }, { "sata1", "sata1lnk", 30 },Signature · 7 lines
1.7.9.5 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
In reply to Thomas PetazzoniThis driver implements the support for the PCIe interfaces on the Marvell Armada 370/XP ARM SoCs. In the future, it might be extended to cover earlier families of Marvell SoCs, such as Dove, Orion and Kirkwood.
The 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.
Since the PCIe interfaces of Marvell SoCs are completely separate and not linked together in a bus, this driver sets up an emulated PCI host bridge, with one PCI-to-PCI bridge as child for each hardware PCIe interface.
In addition, this driver enumerates the different PCIe slots, and for those having a device plugged in, it sets up the necessary address decoding windows, using the new armada_370_xp_alloc_pcie_window() function from mach-mvebu/addr-map.c.
--- .../devicetree/bindings/pci/mvebu-pci.txt | 220 +++++ drivers/pci/host/Kconfig | 4 + drivers/pci/host/Makefile | 4 + drivers/pci/host/pci-mvebu.c | 927 ++++++++++++++++++++ 4 files changed, 1155 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mvebu-pci.txt create mode 100644 drivers/pci/host/Makefile create mode 100644 drivers/pci/host/pci-mvebu.c
Documentation/devicetree/bindings/pci/mvebu-pci.txt new file +220 -0
@@ -0,0 +1,220 @@ +* Marvell EBU PCIe interfaces + +Mandatory properties: +- compatible: one of the following values: + marvell,armada-370-pcie + marvell,armada-xp-pcie +- #address-cells, set to <3> +- #size-cells, set to <2> +- #interrupt-cells, set to <1> +- bus-range: PCI bus numbers covered +- device_type, set to "pci" +- ranges: ranges for the PCI memory and I/O regions, as well as the + MMIO registers to control the PCIe interfaces. + +In addition, the Device Tree node must have sub-nodes describing each +PCIe interface, having the following mandatory properties: +- reg: used only for interrupt mapping, so only the first four bytes + are used to refer to the correct bus number and device number. +- assigned-addresses: reference to the MMIO registers used to control + this PCIe interface. +- clocks: the clock associated to this PCIe interface +- marvell,pcie-port: the physical PCIe port number +- status: either "disabled" or "okay" +- device_type, set to "pci" +- #address-cells, set to <3> +- #size-cells, set to <2> +- #interrupt-cells, set to <1> +- ranges, empty property. +- interrupt-map-mask and interrupt-map, standard PCI properties to + define the mapping of the PCIe interface to interrupt numbers. + +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-xp-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + bus-range = <0x00 0xff>; + + ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */ + 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */ + 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */ + 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */ + 0x82000000 0 0xd0082000 0xd0082000 0 0x00002000 /* Port 3.0 registers */ + 0x82000000 0 0xd0084000 0xd0084000 0 0x00002000 /* Port 1.1 registers */ + 0x82000000 0 0xd0088000 0xd0088000 0 0x00002000 /* Port 1.2 registers */ + 0x82000000 0 0xd008c000 0xd008c000 0 0x00002000 /* Port 1.3 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie at 1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie at 2,0 { + device_type = "pci"; + assigned-addresses = <0x82001000 0 0xd0044000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 59>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + pcie at 3,0 { + device_type = "pci"; + assigned-addresses = <0x82001800 0 0xd0048000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 60>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 7>; + status = "disabled"; + }; + + pcie at 4,0 { + device_type = "pci"; + assigned-addresses = <0x82002000 0 0xd004c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 61>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + pcie at 5,0 { + device_type = "pci"; + assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 9>; + status = "disabled"; + }; + + pcie at 6,0 { + device_type = "pci"; + assigned-addresses = <0x82003000 0 0xd0084000 0 0x2000>; + reg = <0x3000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 63>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 10>; + status = "disabled"; + }; + + pcie at 7,0 { + device_type = "pci"; + assigned-addresses = <0x82003800 0 0xd0088000 0 0x2000>; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 64>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 11>; + status = "disabled"; + }; + + pcie at 8,0 { + device_type = "pci"; + assigned-addresses = <0x82004000 0 0xd008c000 0 0x2000>; + reg = <0x4000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 65>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 12>; + status = "disabled"; + }; + pcie at 9,0 { + device_type = "pci"; + assigned-addresses = <0x82004800 0 0xd0042000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 26>; + status = "disabled"; + }; + + pcie at 10,0 { + device_type = "pci"; + assigned-addresses = <0x82005000 0 0xd0082000 0 0x2000>; + reg = <0x5000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 103>; + marvell,pcie-port = <3>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 27>; + status = "disabled"; + }; +};
drivers/pci/host/Kconfig +4 -0
@@ -1,4 +1,8 @@ menu "PCI host controller drivers" depends on PCI +config PCI_MVEBU + bool "Marvell EBU PCIe controller" + depends on ARCH_MVEBU + endmenu
drivers/pci/host/Makefile new file +4 -0
@@ -0,0 +1,4 @@ +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o +CFLAGS_pci-mvebu.o += \ + -I$(srctree)/arch/arm/plat-orion/include \ + -I$(srctree)/arch/arm/mach-mvebu/include
drivers/pci/host/pci-mvebu.c new file +927 -0
927 lines not on this page · raw message
Signature · 1 line
1.7.9.5
Bjorn Helgaas
maintainerPATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Quoted 15 lines · Thomas Petazzoni
This driver implements the support for the PCIe interfaces on the Marvell Armada 370/XP ARM SoCs. In the future, it might be extended to cover earlier families of Marvell SoCs, such as Dove, Orion and Kirkwood.
The driver implements the
hw_pcioperations needed by the core ARM PCI code to setup PCI devices and get their corresponding IRQs, and thepci_opsoperations that are used by the PCI core to read/write the configuration space of PCI devices.Since the PCIe interfaces of Marvell SoCs are completely separate and not linked together in a bus, this driver sets up an emulated PCI host bridge, with one PCI-to-PCI bridge as child for each hardware PCIe interface.
Quoted 6 lines
In addition, this driver enumerates the different PCIe slots, and for those having a device plugged in, it sets up the necessary address decoding windows, using the new
armada_370_xp_alloc_pcie_window()function frommach-mvebu/addr-map.c.Signed-off-by Thomas Petazzoni <[email protected]>
A few trivial comments below; it's up to you whether you do anything with them or not. It's OK with me if you ignore them :)
The only thing I saw that might be a bug is the resource_size() question in mvebu_pcie_probe().
Bjorn
drivers/pci/host/Makefile line 4
Quoted 10 lines
drivers/pci/host/Makefile new file +4
-0@@ -0,0 +1,4 @@ +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o +CFLAGS_pci-mvebu.o += \ + -I$(srctree)/arch/arm/plat-orion/include \ + -I$(srctree)/arch/arm/mach-mvebu/include
Too bad to have to adjust CFLAGS here. Seems like I remember earlier discussion, but I didn't pay much attention, and if this is the best we can do, I guess it's OK.
Quoted 26 lines
drivers/pci/host/pci-mvebu.c new file +20
-0@@ -0,0 +1,927 @@ +/* +* 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/mbus.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> +
drivers/pci/host/pci-mvebu.c line 30
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+/* +* PCIe unit register offsets. +*/ +#define PCIE_DEV_ID_OFF 0x0000 +#define PCIE_CMD_OFF 0x0004 +#define PCIE_DEV_REV_OFF 0x0008 +#define PCIE_BAR_LO_OFF (n) (0x0010 + ((n) << 3)) +#define PCIE_BAR_HI_OFF (n) (0x0014 + ((n) << 3)) +#define PCIE_HEADER_LOG_4_OFF 0x0128 +#define PCIE_BAR_CTRL_OFF (n) (0x1804 + ((n - 1) * 4))
Strictly speaking, I suppose you should have "(((n) - 1) ..." here.
Quoted 12 lines
drivers/pci/host/pci-mvebu.c new file +12
-0+#define PCIE_WIN04_CTRL_OFF (n) (0x1820 + ((n) << 4)) +#define PCIE_WIN04_BASE_OFF (n) (0x1824 + ((n) << 4)) +#define PCIE_WIN04_REMAP_OFF (n) (0x182c + ((n) << 4)) +#define PCIE_WIN5_CTRL_OFF 0x1880 +#define PCIE_WIN5_BASE_OFF 0x1884 +#define PCIE_WIN5_REMAP_OFF 0x188c +#define PCIE_CONF_ADDR_OFF 0x18f8 +#define PCIE_CONF_ADDR_EN 0x80000000 +#define PCIE_CONF_REG (r) ((((r) & 0xf00) << 16) | ((r) & 0xfc)) +#define PCIE_CONF_BUS (b) (((b) & 0xff) << 16) +#define PCIE_CONF_DEV (d) (((d) & 0x1f) << 11) +#define PCIE_CONF_FUNC (f) (((f) & 0x7) << 8)
drivers/pci/host/pci-mvebu.c line 52
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+#define PCIE_CONF_DATA_OFF 0x18fc +#define PCIE_MASK_OFF 0x1910 +#define PCIE_CTRL_OFF 0x1a00 +#define PCIE_CTRL_X1_MODE 0x0001 +#define PCIE_STAT_OFF 0x1a04 +#define PCIE_STAT_DEV_OFFS 20 +#define PCIE_STAT_DEV_MASK 0x1f +#define PCIE_STAT_BUS_OFFS 8 +#define PCIE_STAT_BUS_MASK 0xff +#define PCIE_STAT_LINK_DOWN 1
Whoever wrote pci_regs.h came up with a style I kind of like: the bit masks are already shifted so you can see where they are in the value, and there are no #defines for the shifts, e.g.,
#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
The users of PCI_EXP_FLAGS_TYPE just have a bare ">> 4" where necessary. It seems like a good compromise that uses only one symbol (good for grepping), gives good visual indication in the header file of how the value is laid out, allows clearing bits without shifts, and clearly shows what's happening at the uses.
But what you have is OK, too :)
Quoted 72 lines
drivers/pci/host/pci-mvebu.c new file +72
-0+#define PCIE_DEBUG_CTRL 0x1a60 +#define PCIE_DEBUG_SOFT_RESET (1<<20) + +/* +* This product ID is registered by Marvell, and used when the Marvell +* SoC is not the root complex, but an endpoint on the PCIe bus. It is +* therefore safe to re-use this PCI ID for our emulated PCI-to-PCI +* bridge. +*/ +#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846 + +/* PCI configuration space of a PCI-to-PCI bridge */ +struct mvebu_sw_pci_bridge { +u16 vendor; +u16 device; +u16 command; +u16 status; +u16 class; +u8 interface; +u8 revision; +u8 bist; +u8 header_type; +u8 latency_timer; +u8 cache_line_size; +u32 bar[2 ]; +u8 primary_bus; +u8 secondary_bus; +u8 subordinate_bus; +u8 secondary_latency_timer; +u8 iobase; +u8 iolimit; +u16 secondary_status; +u16 membase; +u16 memlimit; +u16 prefmembase; +u16 prefmemlimit; +u32 prefbaseupper; +u32 preflimitupper; +u16 iobaseupper; +u16 iolimitupper; +u8 cappointer; +u8 reserved1; +u16 reserved2; +u32 romaddr; +u8 intline; +u8 intpin; +u16 bridgectrl; +}; + +struct mvebu_pcie_port ; + +/* Structure representing all PCIe interfaces */ +struct mvebu_pcie { +struct platform_device *pdev; +struct mvebu_pcie_port *ports; +struct resource io; +struct resource realio; +struct resource mem; +struct resource busn; +int nports; +}; + +/* Structure representing one PCIe interface */ +struct mvebu_pcie_port { +char *name; +void __iomem *base; +spinlock_t conf_lock; +int haslink; +u32 port; +u32 lane; +int devfn; +struct clk *clk;
drivers/pci/host/pci-mvebu.c line 134
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+struct mvebu_sw_pci_bridge bridge; +struct device_node *dn; +struct mvebu_pcie *pcie; +phys_addr_t memwin_base; +size_t memwin_size; +phys_addr_t iowin_base; +size_t iowin_size; +}; + +static int mvebu_pcie_link_up (void __iomem *base)
This could return bool, I guess.
I think I would make
mvebu_pcie_link_up()
mvebu_pcie_set_local_bus_nr()
mvebu_pcie_setup_wins()
mvebu_pcie_setup_hw()
mvebu_pcie_hw_rd_conf()
mvebu_pcie_hw_wr_conf()
all take a "struct mvebu_pcie_port *port" directly rather than having the caller pass in "port->base", but maybe you have a reason for doing otherwise.
Quoted 20 lines
drivers/pci/host/pci-mvebu.c new file +20
-0+{ +return !(readl (base +PCIE_STAT_OFF ) &PCIE_STAT_LINK_DOWN ); +} + +static void mvebu_pcie_set_local_bus_nr (void __iomem *base,int nr) +{ +u32 stat; + + stat =readl (base +PCIE_STAT_OFF ); + stat &= ~(PCIE_STAT_BUS_MASK <<PCIE_STAT_BUS_OFFS ); + stat |= nr <<PCIE_STAT_BUS_OFFS ; +writel (stat, base +PCIE_STAT_OFF ); +} + +/* +* Setup PCIE BARs and Address Decode Wins: +* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks +* WIN[0-3] -> DRAM bank[0-3] +*/ +static void __init mvebu_pcie_setup_wins (void __iomem *base)
drivers/pci/host/pci-mvebu.c line 164
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+{ +const struct mbus_dram_target_info *dram; +u32 size; +int i; + + dram =mv_mbus_dram_info (); + +/* +* First, disable and clear BARs and windows. +*/
Typically single-line comments would be "/* ... */" all on one line.
drivers/pci/host/pci-mvebu.c line 165
Quoted 1 line
drivers/pci/host/pci-mvebu.c new file +1
-0+for (i =1 ; i <=2 ; i++) {
Interesting use of "i <= 2" rather than the typical "i < 3".
Quoted 60 lines
drivers/pci/host/pci-mvebu.c new file +60
-0+writel (0 , base +PCIE_BAR_CTRL_OFF (i)); +writel (0 , base +PCIE_BAR_LO_OFF (i)); +writel (0 , base +PCIE_BAR_HI_OFF (i)); + } + +for (i =0 ; i <5 ; i++) { +writel (0 , base +PCIE_WIN04_CTRL_OFF (i)); +writel (0 , base +PCIE_WIN04_BASE_OFF (i)); +writel (0 , base +PCIE_WIN04_REMAP_OFF (i)); + } + +writel (0 , base +PCIE_WIN5_CTRL_OFF ); +writel (0 , base +PCIE_WIN5_BASE_OFF ); +writel (0 , base +PCIE_WIN5_REMAP_OFF ); + +/* +* Setup windows for DDR banks. Count total DDR size on the fly. +*/ + size =0 ; +for (i =0 ; i < dram->num_cs; i++) { +const struct mbus_dram_window *cs = dram->cs + i; + +writel (cs->base &0xffff0000 , base +PCIE_WIN04_BASE_OFF (i)); +writel (0 , base +PCIE_WIN04_REMAP_OFF (i)); +writel (((cs->size -1 ) &0xffff0000 ) | + (cs->mbus_attr <<8 ) | + (dram->mbus_dram_target_id <<4 ) |1 , + base +PCIE_WIN04_CTRL_OFF (i)); + + size += cs->size; + } + +/* +* Round up 'size' to the nearest power of two. +*/ +if ((size & (size -1 )) !=0 ) + size =1 <<fls (size); + +/* +* Setup BAR[1] to all DRAM banks. +*/ +writel (dram->cs[0 ].base, base +PCIE_BAR_LO_OFF (1 )); +writel (0 , base +PCIE_BAR_HI_OFF (1 )); +writel (((size -1 ) &0xffff0000 ) |1 , base +PCIE_BAR_CTRL_OFF (1 )); +} + +static void __init mvebu_pcie_setup_hw (void __iomem *base) +{ +u16 cmd; +u32 mask; + +/* +* Point PCIe unit MBUS decode windows to DRAM space. +*/ +mvebu_pcie_setup_wins (base); + +/* +* Master + slave enable. +*/ + cmd =readw (base +PCIE_CMD_OFF );
drivers/pci/host/pci-mvebu.c line 235
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+ cmd |=PCI_COMMAND_IO ; + cmd |=PCI_COMMAND_MEMORY ; + cmd |=PCI_COMMAND_MASTER ; +writew (cmd, base +PCIE_CMD_OFF ); + +/* +* Enable interrupt lines A-D. +*/ + mask =readl (base +PCIE_MASK_OFF ); + mask |=0x0f000000 ;
No #defines for these bits?
drivers/pci/host/pci-mvebu.c line 245
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+writel (mask, base +PCIE_MASK_OFF ); +} + +static int mvebu_pcie_hw_rd_conf (void __iomem *base,struct pci_bus *bus, +u32 devfn,int where,int size,u32 *val) +{ + writel(PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
A "PCIE_CONF_ADDR(busnr, devfn, where)" macro would be nice here.
Quoted 30 lines
drivers/pci/host/pci-mvebu.c new file +30
-0+ base + PCIE_CONF_ADDR_OFF); + + *val =readl (base +PCIE_CONF_DATA_OFF ); + +if (size ==1 ) + *val = (*val >> (8 * (where &3 ))) &0xff ; +else if (size ==2 ) + *val = (*val >> (8 * (where &3 ))) &0xffff ; + +return PCIBIOS_SUCCESSFUL ; +} + +static int mvebu_pcie_hw_wr_conf (void __iomem *base,struct pci_bus *bus, +u32 devfn,int where,int size,u32 val) +{ +int ret =PCIBIOS_SUCCESSFUL ; + +writel (PCIE_CONF_BUS (bus->number) | +PCIE_CONF_DEV (PCI_SLOT (devfn)) | +PCIE_CONF_FUNC (PCI_FUNC (devfn)) | +PCIE_CONF_REG (where) |PCIE_CONF_ADDR_EN , + base +PCIE_CONF_ADDR_OFF ); + +if (size ==4 ) +writel (val, base +PCIE_CONF_DATA_OFF ); +else if (size ==2 ) +writew (val, base +PCIE_CONF_DATA_OFF + (where &3 )); +else if (size ==1 ) +writeb (val, base +PCIE_CONF_DATA_OFF + (where &3 )); +else
drivers/pci/host/pci-mvebu.c line 285
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+ ret =PCIBIOS_BAD_REGISTER_NUMBER ; + +return ret; +} + +static void mvebu_pcie_handle_iobase_change (struct mvebu_pcie_port *port) +{ +phys_addr_t iobase; + +/* Are the current iobase/iolimit values invalid? */
I first thought "current ... values" meant "the values before the change." If you used "new values" it might be clearer that this is used to handle *writes* to the window base/size registers, and that we're looking at the values being written.
Quoted 323 lines
drivers/pci/host/pci-mvebu.c new file +323
-0+if (port->bridge.iolimit < port->bridge.iobase || + port->bridge.iolimitupper < port->bridge.iobaseupper) { + +/* If a window was configured, remove it */ +if (port->iowin_base) { +mvebu_mbus_del_window (port->iowin_base, + port->iowin_size); + port->iowin_base =0 ; + port->iowin_size =0 ; + } + +return ; + } + +/* +* We read the PCI-to-PCI bridge emulated registers, and +* calculate the base address and size of the address decoding +* window to setup, according to the PCI-to-PCI bridge +* specifications. iobase is the bus address, port->iowin_base +* is the CPU address. +*/ + iobase = ((port->bridge.iobase &0xF0 ) <<8 ) | + (port->bridge.iobaseupper <<16 ); + port->iowin_base = port->pcie->io.start + iobase; + port->iowin_size = ((0xFFF | ((port->bridge.iolimit &0xF0 ) <<8 ) | + (port->bridge.iolimitupper <<16 )) - + iobase); + +mvebu_mbus_add_window_remap_flags (port->name, port->iowin_base, + port->iowin_size, + iobase, +MVEBU_MBUS_PCI_IO ); + +pci_ioremap_io (iobase, port->iowin_base); +} + +static void mvebu_pcie_handle_membase_change (struct mvebu_pcie_port *port) +{ +/* Are the current membase/memlimit values invalid? */ +if (port->bridge.memlimit < port->bridge.membase) { + +/* If a window was configured, remove it */ +if (port->memwin_base) { +mvebu_mbus_del_window (port->memwin_base, + port->memwin_size); + port->memwin_base =0 ; + port->memwin_size =0 ; + } + +return ; + } + +/* +* We read the PCI-to-PCI bridge emulated registers, and +* calculate the base address and size of the address decoding +* window to setup, according to the PCI-to-PCI bridge +* specifications. +*/ + port->memwin_base = ((port->bridge.membase &0xFFF0 ) <<16 ); + port->memwin_size = + (((port->bridge.memlimit &0xFFF0 ) <<16 ) |0xFFFFF ) - + port->memwin_base; + +mvebu_mbus_add_window_remap_flags (port->name, port->memwin_base, + port->memwin_size, +MVEBU_MBUS_NO_REMAP , +MVEBU_MBUS_PCI_MEM ); +} + +/* +* Initialize the configuration space of the PCI-to-PCI bridge +* associated with the given PCIe interface. +*/ +static void mvebu_sw_pci_bridge_init (struct mvebu_pcie_port *port) +{ +struct mvebu_sw_pci_bridge *bridge = &port->bridge; + +memset (bridge,0 ,sizeof (struct mvebu_sw_pci_bridge )); + + bridge->status =PCI_STATUS_CAP_LIST ; + bridge->class =PCI_CLASS_BRIDGE_PCI ; + bridge->vendor =PCI_VENDOR_ID_MARVELL ; + bridge->device =MARVELL_EMULATED_PCI_PCI_BRIDGE_ID ; + bridge->header_type =PCI_HEADER_TYPE_BRIDGE ; + bridge->cache_line_size =0x10 ; + +/* We support 32 bits I/O addressing */ + bridge->iobase =PCI_IO_RANGE_TYPE_32 ; + bridge->iolimit =PCI_IO_RANGE_TYPE_32 ; +} + +/* +* Read the configuration space of the PCI-to-PCI bridge associated to +* the given PCIe interface. +*/ +static int mvebu_sw_pci_bridge_read (struct mvebu_pcie_port *port, +unsigned int where,int size,u32 *value) +{ +struct mvebu_sw_pci_bridge *bridge = &port->bridge; + +switch (where & ~3 ) { +case PCI_VENDOR_ID : + *value = bridge->device <<16 | bridge->vendor; +break ; + +case PCI_COMMAND : + *value = bridge->status <<16 | bridge->command; +break ; + +case PCI_CLASS_REVISION : + *value = bridge->class <<16 | bridge->interface <<8 | + bridge->revision; +break ; + +case PCI_CACHE_LINE_SIZE : + *value = bridge->bist <<24 | bridge->header_type <<16 | + bridge->latency_timer <<8 | bridge->cache_line_size; +break ; + + case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: + *value = bridge->bar[((where & ~3 ) -PCI_BASE_ADDRESS_0 ) /4 ]; +break ; + +case PCI_PRIMARY_BUS : + *value = (bridge->secondary_latency_timer <<24 | + bridge->subordinate_bus <<16 | + bridge->secondary_bus <<8 | + bridge->primary_bus); +break ; + +case PCI_IO_BASE : + *value = (bridge->secondary_status <<16 | + bridge->iolimit <<8 | + bridge->iobase); +break ; + +case PCI_MEMORY_BASE : + *value = (bridge->memlimit <<16 | bridge->membase); +break ; + +case PCI_PREF_MEMORY_BASE : + *value = (bridge->prefmemlimit <<16 | bridge->prefmembase); +break ; + +case PCI_PREF_BASE_UPPER32 : + *value = bridge->prefbaseupper; +break ; + +case PCI_PREF_LIMIT_UPPER32 : + *value = bridge->preflimitupper; +break ; + +case PCI_IO_BASE_UPPER16 : + *value = (bridge->iolimitupper <<16 | bridge->iobaseupper); +break ; + +case PCI_ROM_ADDRESS1 : + *value =0 ; +break ; + +default : + *value =0xffffffff ; +return PCIBIOS_BAD_REGISTER_NUMBER ; + } + +if (size ==2 ) + *value = (*value >> (8 * (where &3 ))) &0xffff ; +else if (size ==1 ) + *value = (*value >> (8 * (where &3 ))) &0xff ; + +return PCIBIOS_SUCCESSFUL ; +} + +/* Write to the PCI-to-PCI bridge configuration space */ +static int mvebu_sw_pci_bridge_write (struct mvebu_pcie_port *port, +unsigned int where,int size,u32 value) +{ +struct mvebu_sw_pci_bridge *bridge = &port->bridge; +u32 mask, reg; +int err; + +if (size ==4 ) + mask =0x0 ; +else if (size ==2 ) + mask = ~(0xffff << ((where &3 ) *8 )); +else if (size ==1 ) + mask = ~(0xff << ((where &3 ) *8 )); +else +return PCIBIOS_BAD_REGISTER_NUMBER ; + + err =mvebu_sw_pci_bridge_read (port, where & ~3 ,4 , ®); +if (err) +return err; + + value = (reg & mask) | value << ((where &3 ) *8 ); + +switch (where & ~3 ) { +case PCI_COMMAND : + bridge->command = value &0xffff ; + bridge->status = value >>16 ; +break ; + + case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: + bridge->bar[((where & ~3 ) -PCI_BASE_ADDRESS_0 ) /4 ] = value; +break ; + +case PCI_IO_BASE : +/* +* We also keep bit 1 set, it is a read-only bit that +* indicates we support 32 bits addressing for the +* I/O +*/ + bridge->iobase = (value &0xff ) |PCI_IO_RANGE_TYPE_32 ; + bridge->iolimit = ((value >>8 ) &0xff ) |PCI_IO_RANGE_TYPE_32 ; + bridge->secondary_status = value >>16 ; +mvebu_pcie_handle_iobase_change (port); +break ; + +case PCI_MEMORY_BASE : + bridge->membase = value &0xffff ; + bridge->memlimit = value >>16 ; +mvebu_pcie_handle_membase_change (port); +break ; + +case PCI_PREF_MEMORY_BASE : + bridge->prefmembase = value &0xffff ; + bridge->prefmemlimit = value >>16 ; +break ; + +case PCI_PREF_BASE_UPPER32 : + bridge->prefbaseupper = value; +break ; + +case PCI_PREF_LIMIT_UPPER32 : + bridge->preflimitupper = value; +break ; + +case PCI_IO_BASE_UPPER16 : + bridge->iobaseupper = value &0xffff ; + bridge->iolimitupper = value >>16 ; +mvebu_pcie_handle_iobase_change (port); +break ; + +case PCI_PRIMARY_BUS : + bridge->primary_bus = value &0xff ; + bridge->secondary_bus = (value >>8 ) &0xff ; + bridge->subordinate_bus = (value >>16 ) &0xff ; + bridge->secondary_latency_timer = (value >>24 ) &0xff ; +mvebu_pcie_set_local_bus_nr (port->base, bridge->secondary_bus); +break ; + +default : +break ; + } + +return PCIBIOS_SUCCESSFUL ; +} + +static inline struct mvebu_pcie *sys_to_pcie (struct pci_sys_data *sys) +{ +return sys->private_data; +} + +/* Find the PCIe interface that corresponds to the given bus */ +static struct mvebu_pcie_port *mvebu_find_port_from_bus (struct mvebu_pcie *pcie, +int bus) +{ +int porti; + +for (porti =0 ; porti < pcie->nports; porti++) +if (pcie->ports[porti].bridge.secondary_bus == bus) +return &pcie->ports[porti]; + +return NULL ; +} + +/* Find the PCIe interface that corresponds to the given devfn */ +static struct mvebu_pcie_port * +mvebu_find_port_from_devfn (struct mvebu_pcie *pcie,int devfn) +{ +int porti; + +for (porti =0 ; porti < pcie->nports; porti++) +if (pcie->ports[porti].devfn == devfn) +return &pcie->ports[porti]; + +return NULL ; +} + +/* PCI configuration space write function */ +static int mvebu_pcie_wr_conf (struct pci_bus *bus,u32 devfn, +int where,int size,u32 val) +{ +struct mvebu_pcie *pcie =sys_to_pcie (bus->sysdata); + +if (bus->number !=0 ) { +/* +* Accessing a real PCIe interface. +*/ +struct mvebu_pcie_port *port; +unsigned long flags; +int ret; + + port =mvebu_find_port_from_bus (pcie, bus->number); +if (!port) +return PCIBIOS_DEVICE_NOT_FOUND ; + +if (!port->haslink) +return PCIBIOS_DEVICE_NOT_FOUND ; + +if (PCI_SLOT (devfn) !=0 ) +return PCIBIOS_DEVICE_NOT_FOUND ; + +spin_lock_irqsave (&port->conf_lock, flags); + ret =mvebu_pcie_hw_wr_conf (port->base, bus, +PCI_DEVFN (1 ,PCI_FUNC (devfn)), + where, size, val); +spin_unlock_irqrestore (&port->conf_lock, flags); + +return ret; + }else { +/* +* Access the emulated PCI-to-PCI bridges.
drivers/pci/host/pci-mvebu.c line 618
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+*/ +struct mvebu_pcie_port *port; + port =mvebu_find_port_from_devfn (pcie, devfn); +if (!port) +return PCIBIOS_DEVICE_NOT_FOUND ; + +return mvebu_sw_pci_bridge_write (port, where, size, val); + } + +return PCIBIOS_SUCCESSFUL ;
This last "return" is unreachable (I see you omitted it from the rd_conf() path already :)). This would be slightly simpler as:
static struct mvebu_pcie_port *mvebu_find_port(struct mvebu_pcie *pcie,
struct pci_bus *bus, int devfn)
{
int i;
for (i = 0; i < pcie->nports; i++) {
if ((bus->number == 0 && pcie->ports[i].devfn == devfn) ||
(pcie->ports[porti].bridge.secondary_bus == bus->number))
return &pcie->ports[i];
}
return NULL;}
static int mvebu_pcie_wr_conf(struct pci_bus *bus, ...)
{
port = mvebu_find_port(pcie, bus, devfn);
if (!port)
return PCIBIOS_DEVICE_NOT_FOUND; if (bus->number == 0)
return mvebu_sw_pci_bridge_write(port, where, size, val);
if (!port->haslink || PCI_SLOT(devfn) != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
...
return ret;}
Quoted 177 lines
drivers/pci/host/pci-mvebu.c new file +177
-0+} + +/* PCI configuration space read function */ +static int mvebu_pcie_rd_conf (struct pci_bus *bus,u32 devfn,int where, +int size,u32 *val) +{ +struct mvebu_pcie *pcie =sys_to_pcie (bus->sysdata); + +if (bus->number !=0 ) { +/* +* Accessing a real PCIe interface. +*/ +struct mvebu_pcie_port *port; +unsigned long flags; +int ret; + + port =mvebu_find_port_from_bus (pcie, bus->number); +if (!port) { + *val =0xffffffff ; +return PCIBIOS_DEVICE_NOT_FOUND ; + } + +if (!port->haslink ||PCI_SLOT (devfn) !=0 ) { + *val =0xffffffff ; +return PCIBIOS_DEVICE_NOT_FOUND ; + } + +spin_lock_irqsave (&port->conf_lock, flags); + ret =mvebu_pcie_hw_rd_conf (port->base, bus, +PCI_DEVFN (1 ,PCI_FUNC (devfn)), + where, size, val); +spin_unlock_irqrestore (&port->conf_lock, flags); + +return ret; + }else { +/* +* Access the emulated PCI-to-PCI bridges. +*/ +struct mvebu_pcie_port *port; + port =mvebu_find_port_from_devfn (pcie, devfn); +if (!port) { + *val =0xffffffff ; +return PCIBIOS_DEVICE_NOT_FOUND ; + } + +return mvebu_sw_pci_bridge_read (port, where, size, val); + } +} + +static struct pci_ops mvebu_pcie_ops = { + .read = mvebu_pcie_rd_conf, + .write = mvebu_pcie_wr_conf, +}; + +static int __init mvebu_pcie_setup (int nr,struct pci_sys_data *sys) +{ +struct mvebu_pcie *pcie =sys_to_pcie (sys); +int i; + +pci_add_resource_offset (&sys->resources, &pcie->realio, sys->io_offset); +pci_add_resource_offset (&sys->resources, &pcie->mem, sys->mem_offset); +pci_add_resource (&sys->resources, &pcie->busn); + +for (i =0 ; i < pcie->nports; i++) { +struct mvebu_pcie_port *port = &pcie->ports[i]; +mvebu_pcie_setup_hw (port->base); + } + +return 1 ; +} + +static int __init mvebu_pcie_map_irq (const struct pci_dev *dev,u8 slot,u8 pin) +{ +struct of_irq oirq; +int ret; + + ret =of_irq_map_pci (dev, &oirq); +if (ret) +return ret; + +return irq_create_of_mapping (oirq.controller, oirq.specifier, + oirq.size); +} + +static struct pci_bus *mvebu_pcie_scan_bus (int nr,struct pci_sys_data *sys) +{ +struct mvebu_pcie *pcie =sys_to_pcie (sys); +struct pci_bus *bus; + + bus =pci_create_root_bus (&pcie->pdev->dev, sys->busnr, + &mvebu_pcie_ops, sys, &sys->resources); +if (!bus) +return NULL ; + +pci_scan_child_bus (bus); + +return bus; +} + +resource_size_t mvebu_pcie_align_resource (struct pci_dev *dev, +const struct resource *res, +resource_size_t start, +resource_size_t size, +resource_size_t align) +{ +if (dev->bus->number !=0 ) +return start; + +/* +* On the PCI-to-PCI bridge side, the I/O windows must have at +* least a 64 KB size and be aligned on their size, and the +* memory windows must have at least a 1 MB size and be +* aligned on their size +*/ +if (res->flags &IORESOURCE_IO ) +return round_up (start,max ((resource_size_t )SZ_64K , size)); +else if (res->flags &IORESOURCE_MEM ) +return round_up (start,max ((resource_size_t )SZ_1M , size)); +else +return start; +} + +static void mvebu_pcie_enable (struct mvebu_pcie *pcie) +{ +struct hw_pci hw; + +memset (&hw,0 ,sizeof (hw)); + + hw.nr_controllers =1 ; + hw.private_data = (void **)&pcie; + hw.setup = mvebu_pcie_setup; + hw.scan = mvebu_pcie_scan_bus; + hw.map_irq = mvebu_pcie_map_irq; + hw.ops = &mvebu_pcie_ops; + hw.align_resource = mvebu_pcie_align_resource; + +pci_common_init (&hw); +} + +/* +* Looks up the list of register addresses encoded into the reg = +* <...> property for one that matches the given port/lane. Once +* found, maps it. +*/ +static void __iomem *mvebu_pcie_map_registers (struct platform_device *pdev, +struct device_node *np, +struct mvebu_pcie_port *port) +{ +struct resource regs; +int ret =0 ; + + ret =of_address_to_resource (np,0 , ®s); +if (ret) +return NULL ; + +return devm_request_and_ioremap (&pdev->dev, ®s); +} + +static int __init mvebu_pcie_probe (struct platform_device *pdev) +{ +struct mvebu_pcie *pcie; +struct device_node *np = pdev->dev.of_node; +struct of_pci_range range; +struct of_pci_range_parser parser; +struct device_node *child; +int i, ret; + + pcie =devm_kzalloc (&pdev->dev,sizeof (struct mvebu_pcie ), +GFP_KERNEL ); +if (!pcie) +return -ENOMEM ; + + pcie->pdev = pdev; + +if (of_pci_range_parser (&parser, np)) +return -EINVAL ; +
drivers/pci/host/pci-mvebu.c line 805
Quoted 10 lines
drivers/pci/host/pci-mvebu.c new file +10
-0+/* Get the I/O and memory ranges from DT */ +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, np, &pcie->io); +of_pci_range_to_resource (&range, np, &pcie->realio); + pcie->io.name ="I/O" ; + pcie->realio.start =PCIBIOS_MIN_IO ; + pcie->realio.end =min (resource_size (&pcie->io), +IO_SPACE_LIMIT );
Using "resource_size(&pcie->io)" here seems strange -- are you assuming that pcie->io starts at address zero?
Quoted 125 lines
drivers/pci/host/pci-mvebu.c new file +122
-1+ } +if (restype ==IORESOURCE_MEM ) { +of_pci_range_to_resource (&range, np, &pcie->mem); + pcie->mem.name ="MEM" ; + } + } + +/* Get the bus range */ + ret =of_pci_parse_bus_range (np, &pcie->busn); +if (ret) { +dev_err (&pdev->dev,"failed to parse bus-range property: %d\n" , + ret); +return ret; + } + +for_each_child_of_node (pdev->dev.of_node, child) { +if (!of_device_is_available (child)) +continue ; + pcie->nports++; + } + + pcie->ports =devm_kzalloc (&pdev->dev, pcie->nports * +sizeof (struct mvebu_pcie_port ), +GFP_KERNEL ); +if (!pcie->ports) +return -ENOMEM ; + + i =0 ; +for_each_child_of_node (pdev->dev.of_node, child) { +struct mvebu_pcie_port *port = &pcie->ports[i]; + +if (!of_device_is_available (child)) +continue ; + + port->pcie = pcie; + +if (of_property_read_u32 (child,"marvell,pcie-port" , + &port->port)) { +dev_warn (&pdev->dev, +"ignoring PCIe DT node, missing pcie-port property\n" ); +continue ; + } + +if (of_property_read_u32 (child,"marvell,pcie-lane" , + &port->lane)) + port->lane =0 ; + + port->name =kasprintf (GFP_KERNEL ,"pcie%d.%d" , + port->port, port->lane); + + port->devfn =of_pci_get_devfn (child); +if (port->devfn <0 ) +continue ; + + port->base =mvebu_pcie_map_registers (pdev, child, port); +if (!port->base) { +dev_err (&pdev->dev,"PCIe%d.%d: cannot map registers\n" , + port->port, port->lane); +continue ; + } + +if (mvebu_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); + } + + 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); +iounmap (port->base); + port->haslink =0 ; +continue ; + } + + port->dn = child; + +clk_prepare_enable (port->clk); +spin_lock_init (&port->conf_lock); + +mvebu_sw_pci_bridge_init (port); + + i++; + } + +mvebu_pcie_enable (pcie); + +return 0 ; +} + +static const struct of_device_id mvebu_pcie_of_match_table[] = { + { .compatible ="marvell,armada-xp-pcie" , }, + { .compatible ="marvell,armada-370-pcie" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, mvebu_pcie_of_match_table); + +static struct platform_driver mvebu_pcie_driver = { + .driver = { + .owner =THIS_MODULE , + .name ="mvebu-pcie" , + .of_match_table = +of_match_ptr (mvebu_pcie_of_match_table), + }, +}; + +static int mvebu_pcie_init (void ) +{ +return platform_driver_probe (&mvebu_pcie_driver, + mvebu_pcie_probe); +} + +subsys_initcall (mvebu_pcie_init); + +MODULE_AUTHOR ("Thomas Petazzoni <[email protected]>" ); +MODULE_DESCRIPTION ("Marvell EBU PCIe driver" ); +MODULE_LICENSE ("GPLv2" ); --1.7.9.5
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Dear Bjorn Helgaas,
Quoted 10 lines · Bjorn Helgaas
Quoted 2 lines
Signed-off-by: Thomas Petazzoni
<[email protected]>Acked-by Bjorn Helgaas <[email protected]>A few trivial comments below; it's up to you whether you do anything with them or not. It's OK with me if you ignore them :)
The only thing I saw that might be a bug is the
resource_size()question inmvebu_pcie_probe().
Thanks for the review!
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/Makefile new file +0
-0@@ -0,0 +1,4 @@
Quoted 8 lines
drivers/pci/host/Makefile line 4
Quoted 4 lines
drivers/pci/host/Makefile new file +4
-0+obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o +CFLAGS_pci-mvebu.o += \ + -I$(srctree)/arch/arm/plat-orion/include \ + -I$(srctree)/arch/arm/mach-mvebu/includeToo bad to have to adjust CFLAGS here. Seems like I remember earlier discussion, but I didn't pay much attention, and if this is the best we can do, I guess it's OK.
Ah, indeed! This is now longer needed. The plat-orion include was needed to get access to some PCIe functions, which are now part of the driver, and the mach-mvebu header was needed to access some address decoding window related functions, that are now part of the mvebu-mbus driver.
Quoted 3 lines
Quoted 1 line
+#define
PCIE_BAR_CTRL_OFF(n)(0x1804+ ((n - 1) * 4))Strictly speaking, I suppose you should have "(((n) - 1) ..." here.
Correct, thanks.
Quoted 13 lines
drivers/pci/host/Makefile
Quoted 6 lines
drivers/pci/host/Makefile new file +6
-0+#define PCIE_STAT_OFF 0x1a04 +#define PCIE_STAT_DEV_OFFS 20 +#define PCIE_STAT_DEV_MASK 0x1f +#define PCIE_STAT_BUS_OFFS 8 +#define PCIE_STAT_BUS_MASK 0xff +#define PCIE_STAT_LINK_DOWN 1Whoever wrote
pci_regs.hcame up with a style I kind of like: the bit masks are already shifted so you can see where they are in the value, and there are no #defines for the shifts, e.g.,#define
PCI_EXP_FLAGS_TYPE0x00f0/* Device/Port type */
Quoted 7 lines
The users of
PCI_EXP_FLAGS_TYPEjust have a bare ">> 4" where necessary. It seems like a good compromise that uses only one symbol (good for grepping), gives good visual indication in the header file of how the value is laid out, allows clearing bits without shifts, and clearly shows what's happening at the uses.But what you have is OK, too :)
Hum, ok, I'll try to think of it. Maybe too much of a 'big' change at this point, but I'll see.
Quoted 3 lines
Quoted 1 line
+static int
mvebu_pcie_link_up(void __iomem *base)This could return bool, I guess.
Indeed.
Quoted 9 lines
I think I would make
mvebu_pcie_link_up()
mvebu_pcie_set_local_bus_nr()
mvebu_pcie_setup_wins()
mvebu_pcie_setup_hw()
mvebu_pcie_hw_rd_conf()
mvebu_pcie_hw_wr_conf()
Quoted 3 lines
all take a "struct
mvebu_pcie_port*port" directly rather than having the caller pass in "port->base", but maybe you have a reason for doing otherwise.
I'll review this, I think your suggestion makes sense.
Quoted 5 lines
drivers/pci/host/Makefile
Quoted 3 lines
drivers/pci/host/Makefile new file +3
-0+ /* + * First, disable and clear BARs and windows. + */Typically single-line comments would be "/* ... */" all on one line.
Correct.
Quoted 3 lines
Quoted 1 line
+ for (i = 1; i <= 2; i++) {
Interesting use of "i <= 2" rather than the typical "i < 3".
I must confess this code comes from plat-orion/pcie.c, and I just copy/pasted it (note: we intentionally don't use plat-orion/pcie.c to avoid having to have to include a header in plat-orion/include, and this plat-orion/pcie.c should ultimately go away once all Marvell EBU platforms are migrated to use the new PCIe driver).
Quoted 7 lines
drivers/pci/host/Makefile
Quoted 5 lines
drivers/pci/host/Makefile new file +5
-0+ /* + * Enable interrupt lines A-D. + */ + mask = readl(base + PCIE_MASK_OFF); + mask |= 0x0f000000;No #defines for these bits?
Good point.
Quoted 5 lines
Quoted 5 lines
drivers/pci/host/Makefile new file +4
-0+ writel(mask, base + PCIE_MASK_OFF); +} + +static int mvebu_pcie_hw_rd_conf(void __iomem *base, struct
pci_bus*bus,
Quoted 8 lines
drivers/pci/host/Makefile
Quoted 6 lines
+ u32 devfn, int where, int size,
u32 *val) +{drivers/pci/host/Makefile new file +4
-0+ writel(PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,A "
PCIE_CONF_ADDR(busnr, devfn, where)" macro would be nice here.
Right.
Quoted 10 lines
drivers/pci/host/Makefile
Quoted 5 lines
+static void
mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)+{drivers/pci/host/Makefile new file +3
-0+ phys_addr_t iobase; + + /* Are the current iobase/iolimit values invalid? */I first thought "current ... values" meant "the values before the change." If you used "new values" it might be clearer that this is used to handle *writes* to the window base/size registers, and that we're looking at the values being written.
Ok, makes sense indeed.
Quoted 36 lines
drivers/pci/host/Makefile
Quoted 5 lines
+ return mvebu_sw_pci_bridge_write(port, where, size,
val);drivers/pci/host/Makefile new file +3
-0+ } + + return PCIBIOS_SUCCESSFUL;This last "return" is unreachable (I see you omitted it from the
rd_conf()path already :)). This would be slightly simpler as:static struct
mvebu_pcie_port*mvebu_find_port(structmvebu_pcie
*pcie, structpci_bus*bus, int devfn){ int i; for (i = 0; i < pcie->nports; i++) { if ((bus->number == 0 && pcie->ports[i].devfn == devfn) || (pcie->ports[porti].bridge.secondary_bus == bus->number)) return &pcie->ports[i]; } return NULL;}
static int mvebu_pcie_wr_conf(struct pci_bus *bus, ...) { port = mvebu_find_port(pcie, bus, devfn); if (!port) return PCIBIOS_DEVICE_NOT_FOUND;if (bus->number == 0) return mvebu_sw_pci_bridge_write(port, where, size, val); if (!port->haslink || PCI_SLOT(devfn) != 0) return PCIBIOS_DEVICE_NOT_FOUND; ... return ret;
Quoted 1 line
}
Ok, I'll have a look at this.
Quoted 12 lines
Quoted 11 lines
IORESOURCE_TYPE_BITS;drivers/pci/host/Makefile new file +2
-0+ if (restype == IORESOURCE_IO) { + of_pci_range_to_resource(&range, np,
&pcie->io);
+ of_pci_range_to_resource(&range, np,&pcie->realio);drivers/pci/host/Makefile new file +3
-0+ pcie->io.name = "I/O"; + pcie->realio.start = PCIBIOS_MIN_IO; + pcie->realio.end =min(resource_size(&pcie->io),
+IO_SPACE_LIMIT);
Quoted 2 lines
Using "
resource_size(&pcie->io)" here seems strange -- are you assuming thatpcie->iostarts at address zero?
No, I'm assuming PCIBIOS_MIN_IO is always 0. So presumarly, this should be something like:
pcie->realio.end = min(PCIBIOS_MIN_IO + resource_size(&pcie->io), IO_SPACE_LIMIT);
Thanks for all your valuable comments!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Quoted 9 lines · Thomas Petazzoni
Quoted 8 lines
Quoted 5 lines
drivers/pci/host/pci-mvebu.c new file +3
-0+ pcie->io.name ="I/O" ; + pcie->realio.start =PCIBIOS_MIN_IO ; + pcie->realio.end =min(resource_size(&pcie->io),
+IO_SPACE_LIMIT);Using "
resource_size(&pcie->io)" here seems strange -- are you assuming thatpcie->iostarts at address zero?
Quoted 7 lines
No, I'm assuming
PCIBIOS_MIN_IOis always 0. So presumarly, this should be something like:pcie->realio.end = min(PCIBIOS_MIN_IO + resource_size(&pcie->io), IO_SPACE_LIMIT);
Normally PCIBIOS_MIN_IO is 0x1000, since the first 4096 ports are reserved for ISA and PCMCIA compatible drivers and should not be assigned to PCI devices. So the first port should get ports 0x1000 to 0xffff, later ones can used the entire 65536 ports e.g. 0x10000 to 0x1ffff.
Arnd
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Dear Arnd Bergmann,
Quoted 8 lines · Arnd Bergmann
Quoted 7 lines
No, I'm assuming
PCIBIOS_MIN_IOis always 0. So presumarly, this should be something like:pcie->realio.end = min(PCIBIOS_MIN_IO + resource_size(&pcie->io), IO_SPACE_LIMIT);
Quoted 4 lines
Normally
PCIBIOS_MIN_IOis0x1000, since the first 4096 ports are reserved for ISA and PCMCIA compatible drivers and should not be assigned to PCI devices. So the first port should get ports0x1000to0xffff, later ones can used the entire 65536 ports e.g.0x10000to0x1ffff.
Then I guess it should work with the code I'm proposing here, no?
Note: this pcie->realio region is global: it will be shared by all PCIe interfaces.
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Quoted 17 lines · Thomas Petazzoni
Dear Arnd Bergmann,
Quoted 8 lines · Arnd Bergmann
Quoted 7 lines
No, I'm assuming
PCIBIOS_MIN_IOis always 0. So presumarly, this should be something like:pcie->realio.end = min(PCIBIOS_MIN_IO + resource_size(&pcie->io), IO_SPACE_LIMIT);Quoted 4 lines
Normally
PCIBIOS_MIN_IOis0x1000, since the first 4096 ports are reserved for ISA and PCMCIA compatible drivers and should not be assigned to PCI devices. So the first port should get ports0x1000to0xffff, later ones can used the entire 65536 ports e.g.0x10000to0x1ffff.
Quoted 4 lines
Then I guess it should work with the code I'm proposing here, no?
Note: this
pcie->realioregion is global: it will be shared by all PCIe interfaces.
I think it's still wrong, unless you guarantee that resource_start(&pcie->io) is the same as PCIBIOS_MIN_IO.
Why don't you just read the start and end values from the ranges property? I assume you want to run with io_offset=0, so you really need
pcie->realio.type = IORESOURCE_IO; pcie->realio.start = max(PCIBIOS_MIN_IO, range->pci_addr); pcie->realio.end = max(IO_SPACE_LIMIT, range->pci_addr + range->size); Arnd
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Dear Arnd Bergmann,
Quoted 3 lines · Arnd Bergmann
pcie->realio.type = IORESOURCE_IO; pcie->realio.start = max(PCIBIOS_MIN_IO, range->pci_addr); pcie->realio.end = max(IO_SPACE_LIMIT, range->pci_addr + range->size);
Shouldn't this last line be using "min()" so that we guarantee we don't have an I/O region that goes beyond IO_SPACE_LIMIT?
Thanks,
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Quoted 11 lines · Thomas Petazzoni
Dear Arnd Bergmann,
Quoted 3 lines · Arnd Bergmann
pcie->realio.type = IORESOURCE_IO; pcie->realio.start = max(PCIBIOS_MIN_IO, range->pci_addr); pcie->realio.end = max(IO_SPACE_LIMIT, range->pci_addr + range->size);Shouldn't this last line be using "
min()" so that we guarantee we don't have an I/O region that goes beyondIO_SPACE_LIMIT?
Yes, of course. Sorry for not typing what I was thinking ;-)
Arnd
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
In reply to Bjorn HelgaasQuoted 16 lines · Bjorn Helgaas
On Wed, Mar 27, 2013 at 8:40 AM, Thomas Petazzoni
drivers/pci/host/Makefile line 4
Quoted 10 lines
drivers/pci/host/Makefile new file +4
-0@@ -0,0 +1,4 @@ +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o +CFLAGS_pci-mvebu.o += \ + -I$(srctree)/arch/arm/plat-orion/include \ + -I$(srctree)/arch/arm/mach-mvebu/includeToo bad to have to adjust CFLAGS here. Seems like I remember earlier discussion, but I didn't pay much attention, and if this is the best we can do, I guess it's OK.
I'm pretty sure I NAK'ed this part. I'm surprised it's still there.
Arnd
PATCH v7 8/17 pci: PCIe driver for Marvell Armada 370/XP systems
Dear Arnd Bergmann,
Quoted 5 lines · Arnd Bergmann
Quoted 3 lines
Too bad to have to adjust CFLAGS here. Seems like I remember earlier discussion, but I didn't pay much attention, and if this is the best we can do, I guess it's OK.
I'm pretty sure I NAK'ed this part. I'm surprised it's still there.
As I said in my reply to Bjorn, it's a mistake. I did so much efforts to get rid of the mach-mvebu and plat-orion dependencies, that in the end, I forgot that the original reason was to get rid of those special cflags.
For sure, I'll send a v8 that has those cflags removed, they are unneeded.
Sorry for this.
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v7 9/17 arm: mvebu: PCIe support is now available on mvebu
In reply to Thomas PetazzoniNow that the PCIe driver for mvebu has been integrated and all its relevant dependencies, we can mark the ARCH_MVEBU platform has MIGHT_HAVE_PCI, which allows to select the PCI bus support if needed.
--- arch/arm/mach-mvebu/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mach-mvebu/Kconfig +2 -0
@@ -14,6 +14,8 @@ config ARCH_MVEBU select MVEBU_CLK_CPU select MVEBU_CLK_GATING select MVEBU_MBUS + select MIGHT_HAVE_PCI + select PCI_QUIRKS if PCI if ARCH_MVEBU
Signature · 1 line
1.7.9.5
PATCH v7 10/17 arm: mvebu: add PCIe Device Tree informations for Armada 370
In reply to Thomas PetazzoniThe Armada 370 SoC has two 1x PCIe 2.0 interfaces, so we add the necessary Device Tree informations to make these interfaces availabel.
--- arch/arm/boot/dts/armada-370.dtsi | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
arch/arm/boot/dts/armada-370.dtsi +51 -0
@@ -153,5 +153,56 @@ clocks = <&coreclk 0>; }; + pcie-controller { + compatible = "marvell,armada-370-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + bus-range = <0x00 0xff>; + + reg = <0xd0040000 0x2000>, <0xd0080000 0x2000>; + + reg-names = "pcie0.0", "pcie1.0"; + + ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie at 1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie at 2,0 { + device_type = "pci"; + assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 9>; + status = "disabled"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 11/17 arm: mvebu: add PCIe Device Tree informations for Armada XP
In reply to Thomas PetazzoniThe Armada XP SoCs have multiple PCIe interfaces. The MV78230 has 2 PCIe units (one 4x or quad 1x, the other 1x only), the MV78260 has 3 PCIe units (two 4x or quad 1x and one 4x/1x), the MV78460 has 4 PCIe units (two 4x or quad 1x and two 4x/1x). We therefore add the necessary Device Tree informations to make those PCIe interfaces usable.
--- arch/arm/boot/dts/armada-xp-mv78230.dtsi | 104 +++++++++++++++++ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 122 +++++++++++++++++++ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 188 ++++++++++++++++++++++++++++++ 3 files changed, 414 insertions(+)
arch/arm/boot/dts/armada-xp-mv78230.dtsi +104 -0
@@ -76,5 +76,109 @@ #interrupts-cells = <2>; interrupts = <87>, <88>, <89>; }; + + /* + * MV78230 has 2 PCIe units Gen2.0: One unit can be + * configured as x4 or quad x1 lanes. One unit is + * x4/x1. + */ + pcie-controller { + compatible = "marvell,armada-xp-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + bus-range = <0x00 0xff>; + + ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */ + 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */ + 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */ + 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie at 1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie at 2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0044000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 59>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + pcie at 3,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0048000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 60>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 7>; + status = "disabled"; + }; + + pcie at 4,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd004c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 61>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + pcie at 9,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0xd0042000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 26>; + status = "disabled"; + }; + }; }; };
arch/arm/boot/dts/armada-xp-mv78260.dtsi +122 -0
127 lines not on this page · raw message
arch/arm/boot/dts/armada-xp-mv78460.dtsi +188 -0
193 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v7 12/17 arm: mvebu: PCIe Device Tree informations for OpenBlocks AX3-4
In reply to Thomas PetazzoniThe PlatHome OpenBlocks AX3-4 has an internal mini-PCIe slot that can be used to plug mini-PCIe devices. We therefore enable the PCIe interface that corresponds to this slot.
--- arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +9 -0
@@ -139,5 +139,14 @@ usb at d0051000 { status = "okay"; }; + + pcie-controller { + status = "okay"; + /* Internal mini-PCIe connector */ + pcie at 1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 13/17 arm: mvebu: PCIe Device Tree informations for Armada XP DB
In reply to Thomas PetazzoniThe Marvell evaluation board (DB) for the Armada XP SoC has 6 physicals full-size PCIe slots, so we enable the corresponding PCIe interfaces in the Device Tree.
--- arch/arm/boot/dts/armada-xp-db.dts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
arch/arm/boot/dts/armada-xp-db.dts +33 -0
@@ -121,5 +121,38 @@ spi-max-frequency = <20000000>; }; }; + + pcie-controller { + status = "okay"; + + /* + * All 6 slots are physically present as + * standard PCIe slots on the board. + */ + pcie at 1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie at 2,0 { + /* Port 0, Lane 1 */ + status = "okay"; + }; + pcie at 3,0 { + /* Port 0, Lane 2 */ + status = "okay"; + }; + pcie at 4,0 { + /* Port 0, Lane 3 */ + status = "okay"; + }; + pcie at 9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie at 10,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 14/17 arm: mvebu: PCIe Device Tree informations for Armada 370 Mirabox
In reply to Thomas PetazzoniThe Globalscale Mirabox platform uses one PCIe interface for an available mini-PCIe slot, and the other PCIe interface for an internal USB 3.0 controller. We add the necessary Device Tree informations to enable those two interfaces.
--- arch/arm/boot/dts/armada-370-mirabox.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
arch/arm/boot/dts/armada-370-mirabox.dts +16 -0
@@ -70,5 +70,21 @@ usb at d0051000 { status = "okay"; }; + + pcie-controller { + status = "okay"; + + /* Internal mini-PCIe connector */ + pcie at 1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* Connected on the PCB to a USB 3.0 XHCI controller */ + pcie at 2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 15/17 arm: mvebu: PCIe Device Tree informations for Armada 370 DB
In reply to Thomas PetazzoniThe Marvell evaluation board (DB) for the Armada 370 SoC has 2 physical full-size PCIe slots, so we enable the corresponding PCIe interfaces in the Device Tree.
--- arch/arm/boot/dts/armada-370-db.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
arch/arm/boot/dts/armada-370-db.dts +17 -0
@@ -94,5 +94,22 @@ spi-max-frequency = <50000000>; }; }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * both standard PCIe slots and mini-PCIe + * slots on the board. + */ + pcie at 1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie at 2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 16/17 arm: mvebu: PCIe Device Tree informations for Armada XP GP
In reply to Thomas PetazzoniThe Marvell Armada XP GP board has 3 physical full-size PCIe slots, so we enable the corresponding PCIe interfaces in the Device Tree.
--- arch/arm/boot/dts/armada-xp-gp.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
arch/arm/boot/dts/armada-xp-gp.dts +21 -0
@@ -109,5 +109,26 @@ spi-max-frequency = <108000000>; }; }; + + pcie-controller { + status = "okay"; + + /* + * The 3 slots are physically present as + * standard PCIe slots on the board. + */ + pcie at 1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie at 9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie at 10,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; + }; }; };
Signature · 1 line
1.7.9.5
PATCH v7 17/17 arm: mvebu: update defconfig with PCI and USB support
In reply to Thomas PetazzoniNow that we have the necessary drivers and Device Tree informations to support PCIe on Armada 370 and Armada XP, enable the CONFIG_PCI option.
Also, since the Armada 370 Mirabox has a built-in USB XHCI controller connected on the PCIe bus, enable the corresponding options as well.
--- arch/arm/configs/mvebu_defconfig | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/configs/mvebu_defconfig +3 -0
@@ -13,6 +13,8 @@ CONFIG_MACH_ARMADA_370=y CONFIG_MACH_ARMADA_XP=y # CONFIG_CACHE_L2X0 is not set # CONFIG_SWP_EMULATE is not set +CONFIG_PCI=y +CONFIG_PCI_MVEBU=y CONFIG_SMP=y CONFIG_AEABI=y CONFIG_HIGHMEM=y
@@ -53,6 +55,7 @@ CONFIG_USB_SUPPORT=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_XHCI_HCD=y CONFIG_MMC=y CONFIG_MMC_MVSDIO=y CONFIG_NEW_LEDS=y
Signature · 1 line
1.7.9.5
v7 cover PCIe support for the Armada 370 and Armada XP SoCs
In reply to Thomas PetazzoniThomas, Arnd, Olof, Russell, Grant, Bjorn,
Quoted 21 lines · Thomas Petazzoni
Hello,
This series of patches introduces PCIe support for the Marvell Armada 370 and Armada XP. In the future, we plan to extend the driver to cover Kirkwood platforms, and possibly other Marvell EBU platforms as well.
As we are approaching 3.10, I would now like to get formal Acked-by, or disagreements from the following maintainers/developers :
* Grant Likely, as the OF maintainer, for patches 1, 2 and 3
[PATCH v5 01/17] of/pci: Provide support for parsing PCI DT ranges [PATCH v5 02/17] of/pci: Add of_pci_get_devfn() function [PATCH v5 03/17] of/pci: Add of_pci_parse_bus_range() function* Bjorn Helgaas, as the PCI maintainer, for patches 4 and 8
[PATCH v5 04/17] pci: infrastructure to add drivers in
drivers/pci/host[PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
Quoted 8 lines
* Russell King, as the ARM maintainer, for patch 5
[PATCH v5 05/17] arm: pci: add a
align_resourcehook* Arnd Bergmann, Mitch Bradley and Jason Gunthorpe, for patch 8 (the PCIe driver itself), and specifically the Device Tree binding.
[PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
How would you best like to handle this series? I can take just 9-17 without adding any external dependencies to the arm-soc tree. Can each maintainer do the same for each each of the groups above? I have a feeling the answer is no, especially with the dependency on mvebu/cleanup and the mvebu mbus driver currently in my tree. It's probably best to keep this series together. I'd really like to see this in for v3.10 if at all possible.
Thoughts?
thx,
Jason.
Quoted 241 lines
This patch set depends on:
* The arm-soc/mvebu/cleanup branch in Arnd and Olof arm-soc tree
* [PATCH v3 for 3.10] Introduce a Marvell EBU MBus driver
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/156883.htmlFor easier testing, the code has been pushed to:
git://github.com/MISL-EBU-System-SW/mainline-public.gitmarvell-pcie-v7This PATCHv7 follows:
* PATCHv6, sent on March, 26st 2013
* PATCHv5, sent on March, 21st 2013
* PATCHv4, sent on March, 8th 2013
* PATCHv3, sent on February, 12th 2013
* PATCHv2, sent on January, 28th 2013
* RFCv1, sent on December, 7th 2012Changes between v6 and v7:
* Use assigned-addresses in the DT subnodes for the MMIO PCIe registers, in order to align with what Thierry is doing on the Tegra PCIe driver.
* Added empty 'ranges;' properties in the subnodes, as requested by Arnd. Note that due to this, it is not possible to remove the #address-cells and #size-cells properties from the subnodes, as Jason Gunthorpe requested, otherwise the DT compiler complains with:
Warning (
ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #address-cells (2) differs from /soc/pcie-controller (3)Warning (
ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #size-cells (1) differs from /soc/pcie-controller (2)* Use the new RFCv3 patch from Andrew Murray for 'of/pci: Provide support for parsing PCI DT ranges property'.
* Updated the DT binding documentation accordingly.
Changes between v5 and v6:
* Use
pci_create_root_bus()+pci_scan_child_bus()instead ofpci_scan_root_bus(). This is needed to be able to add MSI support later on. Moreover Thierry Reding suggested thatpci_scan_root_bus()"does apci_bus_add_devices(), which is called again inpci_common_init()in the ARM code". Thanks Thierry for pointing out this issue.Changes between v4 and v5:
* Rebased on top of 3.9-rc2 + the new mvebu-mbus driver (v3).
* Changed the names of the PCI DT sub-nodes to match the OF
specifications: they should be named pcie at DD,FF where DD is the device number and FF the function number. Requested by Mitch Bradley.* Add the
device_type= "pci" property at the pcie-controller level. Requested by Mitch Bradley.* Drop patch 'of/pci: Add
of_pci_get_bus()function' because it wasn't actually used in the rest of the patch series.* Updated the patch 'of/pci: Provide support for parsing PCI DT ranges property' to use the latest version proposed by Andrew Murray on the devicetree-discuss@ mailing list.
Changes between v3 and v4:
* Rebased on top of 3.9-rc1.
* Drop patch "ARM: pci: Allow passing per-controller private data" because it was merged in 3.9.
* Drop patch "lib: devres: don't enclose pcim_*() functions in
CONFIG_HAS_IOPORT", because it was merged in 3.9.* Added
CONFIG_PCI_MVEBU=yinmvebu_defconfig, so that the right PCI host controller driver is automatically enabled.* Instead of using the DT 'ranges' property to encode the PCIe register ranges, use a 'reg' property on the main PCIe controller DT node together with a 'reg-names' property. Suggested by Jason Gunthorpe.
* Don't select
PCI_SW_HOST_BRIDGEandPCI_SW_PCI_PCI_BRIDGE, they don't exist anymore. Reported by Bjorn Helgaas.* Added support for the Armada XP GP board.
* Fix the 'ranges' property so that the memory range is an identity map between CPU addresses and bus addresses. Suggested by Arnd Bergmann.
* Changed the 'ranges' property to have the I/O region after the memory region.
* Use the new mvebu-mbus driver API to create/remove address decoding windows when needed. This remove the need to include <
mach/addr-map.h>. Requested by Arnd Bergmann.* Include directly into the driver the few common PCIe functions we were using from
arch/arm/plat-orion/pcie.c. This allows to remove the inclusion of <plat/pcie.h>. Requested by Arnd Bergmann.* Directly set up the address decoding windows when the memory base/limit and I/O base/limit are configured in the PCI-to-PCI bridge instead of relying on the memory and I/O accesses being enabled in the
PCI_COMMANDregister. Suggested by Bjorn Helgaas.* Added some comments on top of the calculations of the I/O base/limit and memory base/limit. Suggested by Arnd Bergmann.
* Changed a bit the way the "realio" resource is created, from suggestions given by Arnd Bergmann.
* Updated the Device Tree binding documentation. Reported by Jason Gunthorpe.
* Instead of using "marvell,armada-370-xp-pcie" as the DT compatible string, use two separate compatible strings:
"marvell,armada-370-pcie" and "marvell,armada-xp-pcie". For now, the driver does the same thing for both.Changes between v2 and v3:
* Use
of_irq_map_pci()instead ofof_irq_map_raw(), as suggested by Andrew Murray. In order to do this, we moved the interrupt-map and interrupt-map-mask DT properties from the main PCIe controller node to the DT subnodes representing each PCIe interface.* Remove the usage of the emulated host bridge.
* Move the emulated PCI-to-PCI bridge code into the Marvell PCI driver itself, in order to allow a tighter integration. Suggested by Bjorn Helgaas and Jason Gunthorpe.
* Make the allocation of address decoding windows dynamic: it's when memory accesses or I/O accesses are enabled at the PCI-to-PCI bridge level that we allocate and setup the corresponding address decoding window. Requested by Bjorn Helgaas.
* Fixed the implementation of I/O accesses to use I/O addresses that fall within the normal
IO_SPACE_LIMIT. This required using the "remap" functionality of address decoding windows, and therefore some changes in the address decoding window allocator. Follows a long discussion about I/O accesses.* Set up a correct bus number in the configuration of the PCIe interfaces so that we don't have to fake bus numbers anymore. Requested by Jason Gunthorpe.
* Fix the
of_pci_get_devfn()implementation according to Stephen Warren's comment.* Use
CFLAGS_instead of ccflags to add the mach-mvebu and plat-orion include paths when building the pci-mvebu driver. This ensures that the include paths are only added when building this specific driver. Requested by Stephen Warren.* Fix the ->resource_align() to only apply on bus 0 (the one on which the emulated PCI-to-PCI bridges sit), and to request an alignment on the size of the window (and not only 64 KB for I/O windows and 1 MB for memory windows).
* Clarified the commit log of "clk: mvebu: create parent-child relation for PCIe clocks on Armada 370"
Thanks,
Thomas
Andrew Murray (1):
of/pci: Provide support for parsing PCI DT ranges propertyThierry Reding (2):
of/pci: Addof_pci_get_devfn()function
of/pci: Addof_pci_parse_bus_range()functionThomas Petazzoni (14):
pci: infrastructure to add drivers indrivers/pci/host
arm: pci: add aalign_resourcehook
clk: mvebu: create parent-child relation for PCIe clocks on Armada370clk: mvebu: add more PCIe clocks for Armada XP
pci: PCIe driver for Marvell Armada 370/XP systems
arm: mvebu: PCIe support is now available on mvebu
arm: mvebu: add PCIe Device Tree informations for Armada 370
arm: mvebu: add PCIe Device Tree informations for Armada XP
arm: mvebu: PCIe Device Tree informations for OpenBlocks AX3-4
arm: mvebu: PCIe Device Tree informations for Armada XP DB
arm: mvebu: PCIe Device Tree informations for Armada 370 Mirabox
arm: mvebu: PCIe Device Tree informations for Armada 370 DB
arm: mvebu: PCIe Device Tree informations for Armada XP GP
arm: mvebu: update defconfig with PCI and USB support.../devicetree/bindings/pci/mvebu-pci.txt | 220 +++++ arch/arm/boot/dts/armada-370-db.dts | 17 + arch/arm/boot/dts/armada-370-mirabox.dts | 16 + arch/arm/boot/dts/armada-370.dtsi | 51 ++ arch/arm/boot/dts/armada-xp-db.dts | 33 + arch/arm/boot/dts/armada-xp-gp.dts | 21 + arch/arm/boot/dts/armada-xp-mv78230.dtsi | 104 +++ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 122 +++ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 188 ++++ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 9 + arch/arm/configs/mvebu_defconfig | 3 + arch/arm/include/asm/mach/pci.h | 11 + arch/arm/kernel/bios32.c | 6 + arch/arm/mach-mvebu/Kconfig | 2 + arch/microblaze/pci/pci-common.c | 110 +-- arch/mips/pci/pci.c | 50 +- arch/powerpc/kernel/pci-common.c | 99 +-- drivers/clk/mvebu/clk-gating-ctrl.c | 18 +- drivers/of/address.c | 63 ++ drivers/of/of_pci.c | 59 +- drivers/pci/Kconfig | 2 + drivers/pci/Makefile | 3 + drivers/pci/host/Kconfig | 8 + drivers/pci/host/Makefile | 4 + drivers/pci/host/pci-mvebu.c | 927 ++++++++++++++++++++ include/linux/of_address.h | 42 + include/linux/of_pci.h | 2 + 27 files changed, 2009 insertions(+), 181 deletions(-) create mode 100644 Documentation/devicetree/bindings/pci/mvebu-pci.txt create mode 100644 drivers/pci/host/Kconfig create mode 100644 drivers/pci/host/Makefile create mode 100644 drivers/pci/host/pci-mvebu.cSignature · 7 lines
1.7.9.5 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
v7 cover PCIe support for the Armada 370 and Armada XP SoCs
In reply to Thomas PetazzoniQuoted 8 lines · Thomas Petazzoni
As we are approaching 3.10, I would now like to get formal Acked-by, or disagreements from the following maintainers/developers :
* Grant Likely, as the OF maintainer, for patches 1, 2 and 3
[PATCH v5 01/17] of/pci: Provide support for parsing PCI DT ranges [PATCH v5 02/17] of/pci: Add of_pci_get_devfn() function [PATCH v5 03/17] of/pci: Add of_pci_parse_bus_range() function
I think Rob Herring can help out in reviewing this, as comaintainer of devicetree stuff.
Yours,
Linus Walleij
v7 cover PCIe support for the Armada 370 and Armada XP SoCs
In reply to Thomas PetazzoniBjorn, Rob, Grant, Russell,
Through this e-mail, I'd like to send you a kind reminder about this patch series. The latest version has been sent a week ago, and there has been only minor changes requested since v4 sent early March, i.e a month ago. Therefore, I would hope for this series to enter 3.10.
But this patch set is touching areas you are the maintainer for, so I would appreciate if you could do a formal review and give your comments or your Ack. I would especially appreciate if you do so in the very near future, so that if there are comments, I'll have the time to fix them and resubmit and updated version in time.
Here are the patches, classified by maintainer area:
* For Grant Likely and Rob Herring, the drivers/of patches:
[PATCHv7 01/17] of/pci: Provide support for parsing PCI DT ranges property
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158556.html
this patch has been around since 3 months now, and has seen a number of iterations, first from Thierry Reding, and then by Andrew Murray. It is also used by Thierry Reding's PCIe driver, and possibly by the upcoming Exynos PCIe driver as well.
[PATCHv7 02/17] of/pci: Add of_pci_get_devfn() function
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158550.html
this patch has been around since 3 months, with no major change since then.
[PATCHv7 03/17] of/pci: Add of_pci_parse_bus_range() function
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158551.html
same thing.
* For Bjorn Helgaas, the drivers/pci/ patches:
[PATCHv7 04/17] pci: infrastructure to add drivers in drivers/pci/host
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158552.html
[PATCHv7 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158566.html
* For Russell King, the arch/arm/kernel/ patch:
[PATCHv7 05/17] arm: pci: add a align_resource hook
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/158553.html
this patch has been around for more than two months now, and has been submitted last week to the patch tracking system, at
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7683/1.
For more details, see the cover letter below, or of course, do not hesitate to request for additional ones as needed.
Thanks a lot for your support,
Thomas
Quoted 263 lines · Thomas Petazzoni
Hello,
This series of patches introduces PCIe support for the Marvell Armada 370 and Armada XP. In the future, we plan to extend the driver to cover Kirkwood platforms, and possibly other Marvell EBU platforms as well.
As we are approaching 3.10, I would now like to get formal Acked-by, or disagreements from the following maintainers/developers :
* Grant Likely, as the OF maintainer, for patches 1, 2 and 3
[PATCH v5 01/17] of/pci: Provide support for parsing PCI DT ranges [PATCH v5 02/17] of/pci: Add of_pci_get_devfn() function [PATCH v5 03/17] of/pci: Add of_pci_parse_bus_range() function* Bjorn Helgaas, as the PCI maintainer, for patches 4 and 8
[PATCH v5 04/17] pci: infrastructure to add drivers in
drivers/pci/host[PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems* Russell King, as the ARM maintainer, for patch 5
[PATCH v5 05/17] arm: pci: add a
align_resourcehook* Arnd Bergmann, Mitch Bradley and Jason Gunthorpe, for patch 8 (the PCIe driver itself), and specifically the Device Tree binding.
[PATCH v5 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
This patch set depends on:
* The arm-soc/mvebu/cleanup branch in Arnd and Olof arm-soc tree
* [PATCH v3 for 3.10] Introduce a Marvell EBU MBus driver
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-March/156883.htmlFor easier testing, the code has been pushed to:
git://github.com/MISL-EBU-System-SW/mainline-public.gitmarvell-pcie-v7This PATCHv7 follows:
* PATCHv6, sent on March, 26st 2013
* PATCHv5, sent on March, 21st 2013
* PATCHv4, sent on March, 8th 2013
* PATCHv3, sent on February, 12th 2013
* PATCHv2, sent on January, 28th 2013
* RFCv1, sent on December, 7th 2012Changes between v6 and v7:
* Use assigned-addresses in the DT subnodes for the MMIO PCIe registers, in order to align with what Thierry is doing on the Tegra PCIe driver.
* Added empty 'ranges;' properties in the subnodes, as requested by Arnd. Note that due to this, it is not possible to remove the #address-cells and #size-cells properties from the subnodes, as Jason Gunthorpe requested, otherwise the DT compiler complains with:
Warning (
ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #address-cells (2) differs from /soc/pcie-controller (3)Warning (
ranges_format): /soc/pcie-controller/pcie at 1,0 has empty "ranges" property but its #size-cells (1) differs from /soc/pcie-controller (2)* Use the new RFCv3 patch from Andrew Murray for 'of/pci: Provide support for parsing PCI DT ranges property'.
* Updated the DT binding documentation accordingly.
Changes between v5 and v6:
* Use
pci_create_root_bus()+pci_scan_child_bus()instead ofpci_scan_root_bus(). This is needed to be able to add MSI support later on. Moreover Thierry Reding suggested thatpci_scan_root_bus()"does apci_bus_add_devices(), which is called again inpci_common_init()in the ARM code". Thanks Thierry for pointing out this issue.Changes between v4 and v5:
* Rebased on top of 3.9-rc2 + the new mvebu-mbus driver (v3).
* Changed the names of the PCI DT sub-nodes to match the OF
specifications: they should be named pcie at DD,FF where DD is the device number and FF the function number. Requested by Mitch Bradley.* Add the
device_type= "pci" property at the pcie-controller level. Requested by Mitch Bradley.* Drop patch 'of/pci: Add
of_pci_get_bus()function' because it wasn't actually used in the rest of the patch series.* Updated the patch 'of/pci: Provide support for parsing PCI DT ranges property' to use the latest version proposed by Andrew Murray on the devicetree-discuss@ mailing list.
Changes between v3 and v4:
* Rebased on top of 3.9-rc1.
* Drop patch "ARM: pci: Allow passing per-controller private data" because it was merged in 3.9.
* Drop patch "lib: devres: don't enclose pcim_*() functions in
CONFIG_HAS_IOPORT", because it was merged in 3.9.* Added
CONFIG_PCI_MVEBU=yinmvebu_defconfig, so that the right PCI host controller driver is automatically enabled.* Instead of using the DT 'ranges' property to encode the PCIe register ranges, use a 'reg' property on the main PCIe controller DT node together with a 'reg-names' property. Suggested by Jason Gunthorpe.
* Don't select
PCI_SW_HOST_BRIDGEandPCI_SW_PCI_PCI_BRIDGE, they don't exist anymore. Reported by Bjorn Helgaas.* Added support for the Armada XP GP board.
* Fix the 'ranges' property so that the memory range is an identity map between CPU addresses and bus addresses. Suggested by Arnd Bergmann.
* Changed the 'ranges' property to have the I/O region after the memory region.
* Use the new mvebu-mbus driver API to create/remove address decoding windows when needed. This remove the need to include <
mach/addr-map.h>. Requested by Arnd Bergmann.* Include directly into the driver the few common PCIe functions we were using from
arch/arm/plat-orion/pcie.c. This allows to remove the inclusion of <plat/pcie.h>. Requested by Arnd Bergmann.* Directly set up the address decoding windows when the memory base/limit and I/O base/limit are configured in the PCI-to-PCI bridge instead of relying on the memory and I/O accesses being enabled in the
PCI_COMMANDregister. Suggested by Bjorn Helgaas.* Added some comments on top of the calculations of the I/O base/limit and memory base/limit. Suggested by Arnd Bergmann.
* Changed a bit the way the "realio" resource is created, from suggestions given by Arnd Bergmann.
* Updated the Device Tree binding documentation. Reported by Jason Gunthorpe.
* Instead of using "marvell,armada-370-xp-pcie" as the DT compatible string, use two separate compatible strings:
"marvell,armada-370-pcie" and "marvell,armada-xp-pcie". For now, the driver does the same thing for both.Changes between v2 and v3:
* Use
of_irq_map_pci()instead ofof_irq_map_raw(), as suggested by Andrew Murray. In order to do this, we moved the interrupt-map and interrupt-map-mask DT properties from the main PCIe controller node to the DT subnodes representing each PCIe interface.* Remove the usage of the emulated host bridge.
* Move the emulated PCI-to-PCI bridge code into the Marvell PCI driver itself, in order to allow a tighter integration. Suggested by Bjorn Helgaas and Jason Gunthorpe.
* Make the allocation of address decoding windows dynamic: it's when memory accesses or I/O accesses are enabled at the PCI-to-PCI bridge level that we allocate and setup the corresponding address decoding window. Requested by Bjorn Helgaas.
* Fixed the implementation of I/O accesses to use I/O addresses that fall within the normal
IO_SPACE_LIMIT. This required using the "remap" functionality of address decoding windows, and therefore some changes in the address decoding window allocator. Follows a long discussion about I/O accesses.* Set up a correct bus number in the configuration of the PCIe interfaces so that we don't have to fake bus numbers anymore. Requested by Jason Gunthorpe.
* Fix the
of_pci_get_devfn()implementation according to Stephen Warren's comment.* Use
CFLAGS_instead of ccflags to add the mach-mvebu and plat-orion include paths when building the pci-mvebu driver. This ensures that the include paths are only added when building this specific driver. Requested by Stephen Warren.* Fix the ->resource_align() to only apply on bus 0 (the one on which the emulated PCI-to-PCI bridges sit), and to request an alignment on the size of the window (and not only 64 KB for I/O windows and 1 MB for memory windows).
* Clarified the commit log of "clk: mvebu: create parent-child relation for PCIe clocks on Armada 370"
Thanks,
Thomas
Andrew Murray (1):
of/pci: Provide support for parsing PCI DT ranges propertyThierry Reding (2):
of/pci: Addof_pci_get_devfn()function
of/pci: Addof_pci_parse_bus_range()functionThomas Petazzoni (14):
pci: infrastructure to add drivers indrivers/pci/host
arm: pci: add aalign_resourcehook
clk: mvebu: create parent-child relation for PCIe clocks on Armada370clk: mvebu: add more PCIe clocks for Armada XP
pci: PCIe driver for Marvell Armada 370/XP systems
arm: mvebu: PCIe support is now available on mvebu
arm: mvebu: add PCIe Device Tree informations for Armada 370
arm: mvebu: add PCIe Device Tree informations for Armada XP
arm: mvebu: PCIe Device Tree informations for OpenBlocks AX3-4
arm: mvebu: PCIe Device Tree informations for Armada XP DB
arm: mvebu: PCIe Device Tree informations for Armada 370 Mirabox
arm: mvebu: PCIe Device Tree informations for Armada 370 DB
arm: mvebu: PCIe Device Tree informations for Armada XP GP
arm: mvebu: update defconfig with PCI and USB support.../devicetree/bindings/pci/mvebu-pci.txt | 220 +++++ arch/arm/boot/dts/armada-370-db.dts | 17 + arch/arm/boot/dts/armada-370-mirabox.dts | 16 + arch/arm/boot/dts/armada-370.dtsi | 51 ++ arch/arm/boot/dts/armada-xp-db.dts | 33 + arch/arm/boot/dts/armada-xp-gp.dts | 21 + arch/arm/boot/dts/armada-xp-mv78230.dtsi | 104 +++ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 122 +++ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 188 ++++ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 9 + arch/arm/configs/mvebu_defconfig | 3 + arch/arm/include/asm/mach/pci.h | 11 + arch/arm/kernel/bios32.c | 6 + arch/arm/mach-mvebu/Kconfig | 2 + arch/microblaze/pci/pci-common.c | 110 +-- arch/mips/pci/pci.c | 50 +- arch/powerpc/kernel/pci-common.c | 99 +-- drivers/clk/mvebu/clk-gating-ctrl.c | 18 +- drivers/of/address.c | 63 ++ drivers/of/of_pci.c | 59 +- drivers/pci/Kconfig | 2 + drivers/pci/Makefile | 3 + drivers/pci/host/Kconfig | 8 + drivers/pci/host/Makefile | 4 + drivers/pci/host/pci-mvebu.c | 927 ++++++++++++++++++++ include/linux/of_address.h | 42 + include/linux/of_pci.h | 2 + 27 files changed, 2009 insertions(+), 181 deletions(-) create mode 100644 Documentation/devicetree/bindings/pci/mvebu-pci.txt create mode 100644 drivers/pci/host/Kconfig create mode 100644 drivers/pci/host/Makefile create mode 100644 drivers/pci/host/pci-mvebu.c
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
v7 cover PCIe support for the Armada 370 and Armada XP SoCs
Quoted 7 lines · Thomas Petazzoni
Bjorn, Rob, Grant, Russell,
Through this e-mail, I'd like to send you a kind reminder about this patch series. The latest version has been sent a week ago, and there has been only minor changes requested since v4 sent early March, i.e a month ago. Therefore, I would hope for this series to enter 3.10.
Quoted 7 lines
But this patch set is touching areas you are the maintainer for, so I would appreciate if you could do a formal review and give your comments or your Ack. I would especially appreciate if you do so in the very near future, so that if there are comments, I'll have the time to fix them and resubmit and updated version in time.
Here are the patches, classified by maintainer area:
FYI I have applied patches 1 thru 3 and converted my PCI DT series for the Integrator to use the new infrastructure, so you can add
on these if you wish. (Working fine.)
The Integrator PCI DT work is dependent on these patches so I also have a strong interest to have them merged somewhere so I can submit my series against them...
Yours,
Linus Walleij