Skip to contentSkip to conversation

PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05

PATCH Superseded Zhou Wang 5 participants 25 messages Jun 3, 2015 – Jul 17, 2015

Subsystems (6)

v2 of 13 Superseded Latest is v13 →

lore
Share & tools
lore

Zhou Wang

author
#0 lore raw

v2 cover PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05

This patchset adds PCIe host support for Hisilicon Soc Hip05. The PCIe hosts use PCIe IP core from Synopsys, So this driver is base on designware PCIe driver.

Hip05 is an ARMv8 architecture Soc. It should be able to use ARM64 PCIe API in designeware PCIe driver.

This patchset is based on v4.1-rc1.

Change from RFC v1:
1. Add 1/4 patch by Arnd which removes align_resource callback in ARM pcibios_align_resource.
2. Change head file in pcie-designware from asm/hardirq.h to linux/hardirq.h.
3. Set pp->root_bus_nr = 0 in dra7xx, exynos, imx6, keystone, layerscape, spear13xx.
4. Remove unnecessary parentheses of some macros in pcie-hisi.
5. Use macro to replace some magic values.
6. Merge two loops together and add some comments about it in context_config function in pcie-hisi.
7. Modify some value of items in pcie node example in binding document.

Change from RFC:
1. delete dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, merge related operations into dw_pcie_host_init.

Link of RFC v1:
- http://www.spinics.net/lists/linux-pci/msg41305.html
Link of RFC:
- http://www.spinics.net/lists/linux-pci/msg40434.html

Zhou Wang (4):
ARM/PCI: remove align_resource callback in pcibios_align_resource
PCI: designware: Add ARM64 support
PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
Documentation: DT: Add Hisilicon PCIe host binding

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 arch/arm/kernel/bios32.c                           |   4 -
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-dra7xx.c                      |   1 +
 drivers/pci/host/pci-exynos.c                      |   2 +-
 drivers/pci/host/pci-imx6.c                        |   2 +-
 drivers/pci/host/pci-keystone.c                    |   2 +-
 drivers/pci/host/pci-layerscape.c                  |   2 +-
 drivers/pci/host/pci-mvebu.c                       |  47 ++--
 drivers/pci/host/pcie-designware.c                 | 128 ++++------
 drivers/pci/host/pcie-hisi.c                       | 258 +++++++++++++++++++++
 drivers/pci/host/pcie-spear13xx.c                  |   2 +-
 drivers/pci/setup-res.c                            |  27 ++-
 include/linux/pci.h                                |   3 +
 15 files changed, 421 insertions(+), 109 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
 create mode 100644 drivers/pci/host/pcie-hisi.c
Signature · 1 line
1.9.1
author
#1 lore raw

PATCH v2 1/4 ARM/PCI: remove align_resource callback in pcibios_align_resource

This patch had added by Arnd Bergmann during last reviewing of v1 patchset[1].

PCI core codes call pcibios_align_resource(). In ARM specific one, it will dereference pci_sys_data and call sys->align_resource. If we try to unify ARM and ARM64 PCIe API in pcie-designware. it will bring kernel crash when run into this dereferencing.

However, in ARM there is only pci-mvebu which implements align_resource. So add align_resource call back in pci_host_bridge structure and override pcibios_align_resource with it.

[1] http://www.spinics.net/lists/linux-pci/msg41671.html

---
 arch/arm/kernel/bios32.c     |  4 ----
 drivers/pci/host/pci-mvebu.c | 47 ++++++++++++++++++++++++++++----------------
 drivers/pci/setup-res.c      | 27 ++++++++++++++++++++-----
 include/linux/pci.h          |  3 +++
 4 files changed, 55 insertions(+), 26 deletions(-)
arch/arm/kernel/bios32.c +0 -4
index fcbbbb1..47588dc 100644
@@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		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)
@@ -597,9 +596,6 @@ 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;
 }
 
drivers/pci/host/pci-mvebu.c +30 -17

76 lines not on this page · raw message

drivers/pci/setup-res.c +22 -5
index 232f925..73abca7 100644
@@ -200,7 +200,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
 }
 
 static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
-		int resno, resource_size_t size, resource_size_t align)
+		int resno, resource_size_t size, resource_size_t align,
+		resource_size_t (*alignf)(void *,
+					  const struct resource *,
+					  resource_size_t,
+					  resource_size_t))
 {
 	struct resource *res = dev->resource + resno;
 	resource_size_t min;
@@ -217,7 +221,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
 	 */
 	ret = pci_bus_alloc_resource(bus, res, size, align, min,
 				     IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
-				     pcibios_align_resource, dev);
+				     alignf, dev);
 	if (ret == 0)
 		return 0;
 
@@ -229,7 +233,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
 	     (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
 		ret = pci_bus_alloc_resource(bus, res, size, align, min,
 					     IORESOURCE_PREFETCH,
-					     pcibios_align_resource, dev);
+					     alignf, dev);
 		if (ret == 0)
 			return 0;
 	}
@@ -242,7 +246,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
 	 */
 	if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
 		ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
-					     pcibios_align_resource, dev);
+					     alignf, dev);
 
 	return ret;
 }
@@ -251,10 +255,23 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
 				resource_size_t size, resource_size_t min_align)
 {
 	struct pci_bus *bus;
+	struct pci_host_bridge *phb;
+	resource_size_t (*alignf)(void *,
+				  const struct resource *,
+				  resource_size_t,
+				  resource_size_t);
 	int ret;
 
 	bus = dev->bus;
-	while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
+	phb = pci_find_host_bridge(bus);
+
+	if (phb->align_resource)
+		alignf = phb->align_resource;
+	else
+		alignf = pcibios_align_resource;
+
+	while ((ret = __pci_assign_resource(bus, dev, resno, size,
+					    min_align, alignf))) {
 		if (!bus->parent || !bus->self->transparent)
 			break;
 		bus = bus->parent;
include/linux/pci.h +3 -0
index 353db8d..39e48fc 100644
@@ -404,6 +404,9 @@ struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
 	struct list_head windows;	/* resource_entry */
+	resource_size_t (*align_resource)(void *data,
+			 const struct resource *res,
+			 resource_size_t size, resource_size_t align);
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
 	unsigned int ignore_reset_delay:1;	/* for entire hierarchy */
Signature · 1 line
1.9.1
#2 lore raw

PATCH v2 1/4 ARM/PCI: remove align_resource callback in pcibios_align_resource

Quoted 13 lines · Zhou Wang
arch/arm/kernel/bios32.c +0 -1
index fcbbbb1..47588dc 100644
@@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		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)

arch/arm/kernel/bios32.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 600

Quoted 8 lines
arch/arm/kernel/bios32.c +0 -3
@@ -597,9 +596,6 @@ 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;
 }

This leaves both 'sys' and 'dev' in this function as unused variables. Please remove them too.

drivers/pci/host/pci-mvebu.c line 26

Quoted 10 lines
drivers/pci/host/pci-mvebu.c +2 -0
index 1ab8635..155d05f 100644
@@ -22,6 +22,8 @@
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 
+#include "../pci.h" /* HACK to see pci_find_host_bridge */
+

Wouldn't it be better to promote pci_find_host_bridge to be declared in include/linux/pci.h instead?

Thanks,

James

Quoted 74 lines
drivers/pci/host/pci-mvebu.c +28 -17
 /*
  * PCIe unit register offsets.
  */
@@ -751,27 +753,20 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 	return 1;
 }
 
-static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+static resource_size_t mvebu_pcie_align_resource(void *data,
+						 const struct resource *res,
+						 resource_size_t size,
+						 resource_size_t align)
 {
-	struct mvebu_pcie *pcie = sys_to_pcie(sys);
-	struct pci_bus *bus;
+	struct pci_dev *dev = data;
 
-	bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
-				  &mvebu_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
+	resource_size_t start = res->start;
 
-	pci_scan_child_bus(bus);
+	if (res->flags & IORESOURCE_IO && start & 0x300)
+		start = (start + 0x3ff) & ~0x3ff;
 
-	return bus;
-}
+	start = (start + align - 1) & ~(align - 1);
 
-static 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;
 
@@ -796,6 +791,25 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 		return start;
 }
 
+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_host_bridge *phb;
+	struct pci_bus *bus;
+
+	bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
+				  &mvebu_pcie_ops, sys, &sys->resources);
+	if (!bus)
+		return NULL;
+
+	phb = pci_find_host_bridge(bus);
+	phb->align_resource = mvebu_pcie_align_resource;
+
+	pci_scan_child_bus(bus);
+
+	return bus;
+}
+
 static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 {
 	struct hw_pci hw;
@@ -812,7 +826,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 	hw.scan           = mvebu_pcie_scan_bus;
 	hw.map_irq        = of_irq_parse_and_map_pci;
 	hw.ops            = &mvebu_pcie_ops;
-	hw.align_resource = mvebu_pcie_align_resource;
 
 	pci_common_init(&hw);
 }
author
#3 lore raw

PATCH v2 1/4 ARM/PCI: remove align_resource callback in pcibios_align_resource

Quoted 17 lines · James Morse
Quoted 16 lines · Zhou Wang
arch/arm/kernel/bios32.c +0 -1
index fcbbbb1..47588dc 100644
@@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		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)
@@ -597,9 +596,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 
 	start = (start + align - 1) & ~(align - 1);
 
Quoted 9 lines

arch/arm/kernel/bios32.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 600

Quoted 5 lines
arch/arm/kernel/bios32.c +0 -3
-	if (sys->align_resource)
-		return sys->align_resource(dev, res, start, size, align);
-
 	return start;
 }

This leaves both 'sys' and 'dev' in this function as unused variables. Please remove them too.

Right, will do in next version.

Quoted 15 lines

drivers/pci/host/pci-mvebu.c line 26

Quoted 10 lines
drivers/pci/host/pci-mvebu.c +2 -0
index 1ab8635..155d05f 100644
@@ -22,6 +22,8 @@
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 
+#include "../pci.h" /* HACK to see pci_find_host_bridge */
+

Wouldn't it be better to promote pci_find_host_bridge to be declared in include/linux/pci.h instead?

Quoted 4 lines

Thanks,

James

The files which use pci_find_host_bridge are all under drivers/pci, so maybe putting in drivers/pci/pci.h is better ?

Many thanks for reviewing?
Zhou

Quoted 78 lines
Quoted 67 lines
drivers/pci/host/pci-mvebu.c +28 -16
 /*
  * PCIe unit register offsets.
  */
@@ -751,27 +753,20 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 	return 1;
 }
 
-static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+static resource_size_t mvebu_pcie_align_resource(void *data,
+						 const struct resource *res,
+						 resource_size_t size,
+						 resource_size_t align)
 {
-	struct mvebu_pcie *pcie = sys_to_pcie(sys);
-	struct pci_bus *bus;
+	struct pci_dev *dev = data;
 
-	bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
-				  &mvebu_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
+	resource_size_t start = res->start;
 
-	pci_scan_child_bus(bus);
+	if (res->flags & IORESOURCE_IO && start & 0x300)
+		start = (start + 0x3ff) & ~0x3ff;
 
-	return bus;
-}
+	start = (start + align - 1) & ~(align - 1);
 
-static 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;
 
@@ -796,6 +791,25 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 		return start;
 }
 
+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_host_bridge *phb;
+	struct pci_bus *bus;
+
+	bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
+				  &mvebu_pcie_ops, sys, &sys->resources);
+	if (!bus)
+		return NULL;
+
+	phb = pci_find_host_bridge(bus);
+	phb->align_resource = mvebu_pcie_align_resource;
+
+	pci_scan_child_bus(bus);
+
+	return bus;
+}
+
 static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 {
 	struct hw_pci hw;

drivers/pci/host/pci-mvebu.c static void mvebu_pcie_enable(struct mvebu_pcie *pcie) · line 831

Quoted 7 lines
drivers/pci/host/pci-mvebu.c +0 -1
@@ -812,7 +826,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 	hw.scan           = mvebu_pcie_scan_bus;
 	hw.map_irq        = of_irq_parse_and_map_pci;
 	hw.ops            = &mvebu_pcie_ops;
-	hw.align_resource = mvebu_pcie_align_resource;
 
 	pci_common_init(&hw);
 }

.

author
#4 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

In reply to Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

I am not very clear about I/O resource management:

Quoted 6 lines
	if (global_io_offset < SZ_1M && pp->io_size > 0) {
		pci_ioremap_io(global_io_offset, pp->io_base);
		global_io_offset += SZ_64K;
		pci_add_resource_offset(&res, &pp->io,
					global_io_offset - pp->io_bus_addr);
	}

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 128 +++++++++++++++----------------------
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 7 files changed, 56 insertions(+), 83 deletions(-)
drivers/pci/host/pci-dra7xx.c +1 -0
index 2d57e19..5c8b6ab 100644
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
drivers/pci/host/pci-exynos.c +1 -1
index c139237..4b6db6c 100644
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-imx6.c +1 -1
index fdb9536..c4a80c5 100644
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-keystone.c +1 -1
index 75333b0..df91f5e 100644
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +50 -78

200 lines not on this page · raw message

drivers/pci/host/pcie-spear13xx.c +1 -1
index 020d788..e78ddf8 100644
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
Signature · 1 line
1.9.1
#5 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 12 lines · Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

I am not very clear about I/O resource management:

Quoted 6 lines
	if (global_io_offset < SZ_1M && pp->io_size > 0) {
		pci_ioremap_io(global_io_offset, pp->io_base);
		global_io_offset += SZ_64K;
		pci_add_resource_offset(&res, &pp->io,
					global_io_offset - pp->io_bus_addr);
	}
Quoted 5 lines

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

I have tested this on a 'Freescale i.MX6 Quad SABRE Lite Board', which also uses a designware pcie host controller (PCI_IMX6). Booted, removed/rescanned the bus, then scanned for wireless access points using the b43 driver. Please note my change below.

Quoted 87 lines
drivers/pci/host/pcie-designware.c +13 -15
index 2e9f84f..b3f0ac7 100644
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,17 +68,10 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
 static unsigned long global_io_offset;
 
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
-
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
 	*val = readl(addr);
@@ -238,7 +232,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -281,7 +275,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -310,7 +304,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -342,13 +336,15 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 515

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the below arm64 code.

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

Quoted 115 lines
drivers/pci/host/pcie-designware.c +25 -63
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
author
#6 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 19 lines · James Morse
Quoted 12 lines · Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

I am not very clear about I/O resource management:

Quoted 6 lines
	if (global_io_offset < SZ_1M && pp->io_size > 0) {
		pci_ioremap_io(global_io_offset, pp->io_base);
		global_io_offset += SZ_64K;
		pci_add_resource_offset(&res, &pp->io,
					global_io_offset - pp->io_bus_addr);
	}
Quoted 5 lines

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

Quoted 7 lines

I have tested this on a 'Freescale i.MX6 Quad SABRE Lite Board', which also uses a designware pcie host controller (PCI_IMX6). Booted, removed/rescanned the bus, then scanned for wireless access points using the b43 driver. Please note my change below.

Hi James,

Many thanks for your help to test :)

Quoted 101 lines
Quoted 87 lines
drivers/pci/host/pcie-designware.c +13 -15
index 2e9f84f..b3f0ac7 100644
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,17 +68,10 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
 static unsigned long global_io_offset;
 
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
-
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
 	*val = readl(addr);
@@ -238,7 +232,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -281,7 +275,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -310,7 +304,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -342,13 +336,15 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 515

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the below arm64 code.

Quoted 3 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use a PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O Bar.

Quoted 9 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Quoted 4 lines

Thanks,

James

OK, will modify this in next version.

Best Regards and thanks again for your test,
Zhou

Quoted 119 lines
Quoted 105 lines
drivers/pci/host/pcie-designware.c +25 -56
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 736

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;

.

#7 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 39 lines
Quoted 39 lines
Quoted 25 lines
drivers/pci/host/pcie-designware.c +8 -4
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 515

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the below arm64 code.

Quoted 7 lines
Quoted 3 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use a PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this, so even if you had a PCIe card with I/O bar it would not work on arm64 as the code stands. Remember that I/O space on arm/arm64 works as a memory access with offset from PCI_IOBASE and that's the value you get in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and arm64 so, as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 146 lines
Quoted 10 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 3 lines
drivers/pci/host/pcie-designware.c +2 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Quoted 4 lines

Thanks,

James

OK, will modify this in next version.

Best Regards and thanks again for your test,
Zhou

Quoted 110 lines
Quoted 110 lines
drivers/pci/host/pcie-designware.c +25 -61
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
Quoted 9 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 736

Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -2
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;

.

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the resources associated to each pci host bridge window. The resources now are not copied to the designware pcie_port pp, instead they are passed by pointer.

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I have also included all the changes about the other drivers

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

It needs to be tested.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 242 +++++++++++++++----------------------
 drivers/pci/host/pcie-designware.h |  10 +-
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 8 files changed, 109 insertions(+), 154 deletions(-)
drivers/pci/host/pci-dra7xx.c +1 -0
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
drivers/pci/host/pci-exynos.c +1 -1
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-imx6.c +1 -1
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-keystone.c +1 -1
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +2 -10
index 2e9f84f..31b29a5 100644
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,16 +68,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) -{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)  { @@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)  {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);

+ struct pcie_port *pp = desc->dev->bus->sysdata;

pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
order_base_2(no_irqs));
@@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, {
int irq, pos;
struct msi_msg msg;
- struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+ struct pcie_port *pp = pdev->bus->sysdata;

if (desc->msi_attrib.is_msix)
return -EINVAL;
@@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) {
struct irq_data *data = irq_get_irq_data(irq);
struct msi_desc *msi = irq_data_get_msi(data);
- struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+ struct pcie_port *pp = msi->dev->bus->sysdata;

clear_irq_range(pp, irq, 1, data->hwirq); } @@ -342,16 +334,24 @@ static const struct irq_domain_ops msi_domain_ops = { .map = dw_pcie_msi_map,
};

-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
{
struct device_node *np = pp->dev->of_node; struct platform_device *pdev = to_platform_device(pp->dev);
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
struct resource *cfg_res;
+ LIST_HEAD(res);
u32 val, na, ns;
const __be32 *addrp;
int i, index, ret;
+ int rlen;
+ struct pci_host_bridge_window *win;
+ const __be32 *parser_range_end = of_get_property(np, "ranges", &rlen);
+
+ if (parser_range_end == NULL)
+ return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+

/* Find the address cell size and the number of cells in order to get
* the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
dev_err(pp->dev, "missing *config* reg space\n");
}

- if (of_pci_range_parser_init(&parser, np)) {
- dev_err(pp->dev, "missing ranges property\n");
- return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+ if (ret)
+ return ret;

/* 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, &pp->io);
- pp->io.name = "I/O";
- pp->io.start = max_t(resource_size_t,
- PCIBIOS_MIN_IO,
- range.pci_addr + global_io_offset);
- pp->io.end = min_t(resource_size_t,

-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);

- pp->io_size = resource_size(&pp->io);
- pp->io_bus_addr = range.pci_addr;
- pp->io_base = range.cpu_addr;
-
- /* Find the untranslated IO space address */
- pp->io_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == IORESOURCE_MEM) {
- of_pci_range_to_resource(&range, np, &pp->mem);
- pp->mem.name = "MEM";
- pp->mem_size = resource_size(&pp->mem);
- pp->mem_bus_addr = range.pci_addr;
-
- /* Find the untranslated MEM space address */
- pp->mem_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == 0) {
- of_pci_range_to_resource(&range, np, &pp->cfg);
- pp->cfg0_size = resource_size(&pp->cfg)/2;
- pp->cfg1_size = resource_size(&pp->cfg)/2;
- pp->cfg0_base = pp->cfg.start;
- pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+ list_for_each_entry(win, &res, list) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+ pp->io = win->res;
+ pp->io->name = "I/O";
+ pp->io_size = resource_size(pp->io);
+ pp->io_bus_addr = pp->io->start - win->offset;
+ /* magic 5 below comes from magic na and ns in
+ * of_pci_range_parser_init() */
+ pp->io_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ ret = pci_remap_iospace(pp->io, pp->io_base);
+ if (ret) {
+ dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+ ret, pp->io);
+ continue;
+ }
+ break;
+ case IORESOURCE_MEM:
+ pp->mem = win->res;
+ pp->mem->name = "MEM";
+ pp->mem_size = resource_size(pp->mem);
+ pp->mem_bus_addr = pp->mem->start - win->offset;
+ pp->mem_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ break;
+ case 0:
+ pp->cfg = win->res;
+ pp->cfg0_size = resource_size(pp->cfg)/2;
+ pp->cfg1_size = resource_size(pp->cfg)/2;
+ pp->cfg0_base = pp->cfg->start;
+ pp->cfg1_base = pp->cfg->start + pp->cfg0_size;

/* Find the untranslated configuration space address */
- pp->cfg0_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- pp->cfg1_mod_base = pp->cfg0_mod_base +
- pp->cfg0_size;
+ pp->cfg0_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+ break;
+ case IORESOURCE_BUS:
+ pp->busn = win->res;
+ break;
+ default:
+ continue;
}
}

- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
- pp->busn.name = np->name;
- pp->busn.start = 0;
- pp->busn.end = 0xff;
- pp->busn.flags = IORESOURCE_BUS;
- dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
- ret, &pp->busn);
- }
-
if (!pp->dbi_base) {
- pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
- resource_size(&pp->cfg));
+ pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+ resource_size(pp->cfg));
if (!pp->dbi_base) {
dev_err(pp->dev, "error with ioremap\n"); return -ENOMEM;
}
}

- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;

if (!pp->va_cfg0_base) {
pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (pp->ops->host_init)
pp->ops->host_init(pp);

- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;

/* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;

- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);

-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+ pp, &res);
+ if (!bus)
+ return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+ bus->msi = &dw_pcie_msi_chip;
#endif

- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+ pp->ops->scan_bus(pp);

- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); #endif
+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);

return 0;
}
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = { .write = dw_pcie_wr_conf,
};

-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
- sys->io_offset = global_io_offset - pp->io_bus_addr;
- pci_ioremap_io(global_io_offset, pp->io_base);
- global_io_offset += SZ_64K;
- pci_add_resource_offset(&sys->resources, &pp->io,
- sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
- pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) -{
- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
- &dw_pcie_ops, sys, &sys->resources);
- if (!bus)
- return NULL;
-
- pci_scan_child_bus(bus);
-
- if (bus && pp->ops->scan_bus)
- pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{
- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
- irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup = dw_pcie_setup,
- .scan = dw_pcie_scan_bus,
- .map_irq = dw_pcie_map_irq,
-};
-
void dw_pcie_setup_rc(struct pcie_port *pp) {
u32 val;

drivers/pci/host/pcie-designware.h +5 -5
index d0bbd27..ab78710 100644
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
drivers/pci/host/pcie-spear13xx.c +1 -1
index 020d788..e78ddf8 100644
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);

------------------------------------
------------------------------------

Quoted 238 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux-
pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
(quoted diff) +2 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 499

Quoted 8 lines
(quoted diff) +1 -0
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 514

Quoted 5 lines
(quoted diff) +5 -0
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the

below arm64 code.

Quoted 8 lines
Quoted 4 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use a PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O

Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this, so even if you had a PCIe card with I/O bar it would not work on arm64 as the code stands. Remember that I/O space on arm/arm64 works as a memory access with offset from PCI_IOBASE and that's the value you
get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and arm64 so, as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 18 lines
Quoted 11 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 4 lines
(quoted diff) +3 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Quoted 4 lines

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 522

Quoted 5 lines
(quoted diff) +5 -0
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 528

Quoted 6 lines
(quoted diff) +6 -0
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +5 -2
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 539

Quoted 4 lines
(quoted diff) +3 -1
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

Review static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
(quoted diff) +4 -0
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 7 lines
Quoted 7 lines

Review static int dw_pcie_valid_config(struct · line 689

Quoted 7 lines
(quoted diff) +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus

*bus, u32 devfn,

Quoted 82 lines
Quoted 11 lines
Quoted 11 lines
(quoted diff) +1 -2
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
(quoted diff) +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-

Review

Quoted 10 lines
(quoted diff) +0 -10
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 39 lines
Quoted 39 lines
(quoted diff) +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

(quoted diff) +0 -18
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

(quoted diff) +0 -13
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
Quoted 9 lines

Review

Quoted 5 lines
(quoted diff) +0 -3
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;

.

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html

author
#9 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 21 lines · Gabriele Paoloni

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the resources associated to each pci host bridge window. The resources now are not copied to the designware pcie_port pp, instead they are passed by pointer.

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I have also included all the changes about the other drivers

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors about this patch. And I think this patch is a experimental one, it could not be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

(quoted diff) +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);

Review

Quoted 10 lines
(quoted diff) +4 -2
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Quoted 554 lines
(quoted diff) +53 -58
+	const __be32 *parser_range_end = of_get_property(np, "ranges", &rlen);
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to get
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	list_for_each_entry(win, &res, list) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
(quoted diff) +33 -11
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, 
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); #endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)

{

(quoted diff) +1 -56
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) -{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;
drivers/pci/host/pcie-designware.h +5 -5
index d0bbd27..ab78710 100644
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
drivers/pci/host/pcie-spear13xx.c +1 -3
index 020d788..e78ddf8 100644
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 155 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux-
pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
(quoted diff) +2 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 499

Quoted 8 lines
(quoted diff) +1 -0
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 514

Quoted 5 lines
(quoted diff) +5 -0
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the

below arm64 code.

Quoted 8 lines
Quoted 4 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use a PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O

Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this, so even if you had a PCIe card with I/O bar it would not work on arm64 as the code stands. Remember that I/O space on arm/arm64 works as a memory access with offset from PCI_IOBASE and that's the value you
get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and arm64 so, as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 18 lines
Quoted 11 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 4 lines
(quoted diff) +3 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Quoted 4 lines

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 522

Quoted 5 lines
(quoted diff) +5 -0
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 528

Quoted 6 lines
(quoted diff) +6 -0
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +5 -2
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 539

Quoted 4 lines
(quoted diff) +3 -1
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

Review static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
(quoted diff) +4 -0
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
(quoted diff) +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
Quoted 87 lines
Quoted 1 line
Quoted 1 line

Review static int dw_pcie_valid_config(struct · line 689

Quoted 1 line
(quoted diff) +0 -0
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus

*bus, u32 devfn,

Quoted 82 lines
Quoted 11 lines
Quoted 11 lines
(quoted diff) +1 -2
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
(quoted diff) +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-

Review

Quoted 10 lines
(quoted diff) +0 -10
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 39 lines
Quoted 39 lines
(quoted diff) +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

(quoted diff) +0 -18
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

(quoted diff) +0 -13
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
Quoted 9 lines

Review

Quoted 5 lines
(quoted diff) +0 -3
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;

.

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html

.

#10 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Hi Zhou Wang

I apologize, I made a mistake as I didn't rebase the patch on the latest Kernel (where I was convinced I did), my bad.

The patch below is based on v4.1-rc7

It passes checkpatch and compiles OK

Cheers

Gab

-------------------------------------------
-------------------------------------------
This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64 on Linux 4.1-rc7.

It needs to be tested.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 242 +++++++++++++++----------------------
 drivers/pci/host/pcie-designware.h |  10 +-
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 8 files changed, 109 insertions(+), 154 deletions(-)
drivers/pci/host/pci-dra7xx.c +1 -0
index 2d57e19..5c8b6ab 100644
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
drivers/pci/host/pci-exynos.c +1 -1
index c139237..4b6db6c 100644
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-imx6.c +1 -1
index fdb9536..c4a80c5 100644
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-keystone.c +1 -1
index 75333b0..df91f5e 100644
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +98 -144

337 lines not on this page · raw message

drivers/pci/host/pcie-designware.h +5 -5
index d0bbd27..ab78710 100644
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
drivers/pci/host/pcie-spear13xx.c +1 -1
index 020d788..e78ddf8 100644
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);

--------------------------------------------------
--------------------------------------------------

Quoted 671 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 3 lines · Gabriele Paoloni

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the resources associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

(quoted diff) +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);

Review

Quoted 10 lines
(quoted diff) +4 -2
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Review

Quoted 1 line
(quoted diff) +1 -0
+	const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

Review

Quoted 7 lines
(quoted diff) +5 -0
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to

get

Quoted 56 lines
(quoted diff) +7 -41
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	list_for_each_entry(win, &res, list) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;

Review int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
(quoted diff) +10 -0
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
(quoted diff) +10 -0
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -

Review int dw_pcie_host_init(struct pcie_port *pp) · line 417

Quoted 10 lines
(quoted diff) +8 -0
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address

*/

Quoted 13 lines
(quoted diff) +9 -4
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;

Review int dw_pcie_host_init(struct pcie_port *pp) · line 437

Quoted 10 lines
(quoted diff) +0 -7
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
(quoted diff) +3 -6
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
Quoted 1 line

pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

Review

Quoted 10 lines
(quoted diff) +3 -2
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Review

Quoted 1 line
(quoted diff) +1 -0
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

Review

Quoted 4 lines
(quoted diff) +4 -0
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
(quoted diff) +15 -5
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 

Review

Quoted 10 lines
(quoted diff) +6 -3
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Review static int dw_pcie_valid_config(struct pcie_port

Quoted 7 lines
(quoted diff) +3 -0
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

Review static int dw_pcie_valid_config(struct pcie_port · line 670

Quoted 7 lines
(quoted diff) +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,

Review

Quoted 7 lines
(quoted diff) +0 -0
 			int where, int size, u32 val)

{

(quoted diff) +1 -1
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 19 lines
(quoted diff) +0 -15
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Review

Quoted 6 lines
(quoted diff) +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys) -{

Quoted 8 lines
(quoted diff) +0 -8
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;

Review

Quoted 10 lines
(quoted diff) +0 -10
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines
(quoted diff) +0 -16
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 68 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 58 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux-
pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
(quoted diff) +2 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 499

Quoted 8 lines
(quoted diff) +1 -0
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 22 lines
Quoted 22 lines
Quoted 9 lines
(quoted diff) +5 -3
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

Review int dw_pcie_host_init(struct pcie_port *pp) · line 514

Quoted 10 lines
(quoted diff) +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the

Quoted 7 lines
Quoted 7 lines

below arm64 code.

Quoted 6 lines
Quoted 4 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use

a

Quoted 8 lines
Quoted 8 lines
Quoted 2 lines

PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O

Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works as

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and arm64

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 106 lines
Quoted 106 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 522

Quoted 5 lines
(quoted diff) +5 -0
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 528

Quoted 6 lines
(quoted diff) +6 -0
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +5 -2
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 539

Quoted 4 lines
(quoted diff) +3 -1
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

Review static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
(quoted diff) +4 -0
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 7 lines
Quoted 7 lines

Review static int dw_pcie_valid_config(struct · line 689

Quoted 7 lines
(quoted diff) +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines
(quoted diff) +1 -2
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
(quoted diff) +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-

Review

Quoted 10 lines
(quoted diff) +0 -10
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
(quoted diff) +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

(quoted diff) +0 -10
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review

Quoted 8 lines
(quoted diff) +0 -8
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

(quoted diff) +0 -8
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;

Review

Quoted 10 lines
(quoted diff) +0 -8
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;

.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to majordomo at vger.kernel.org More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

author
#11 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 4 lines · Gabriele Paoloni

Hi Zhou Wang

I apologize, I made a mistake as I didn't rebase the patch on the latest Kernel (where I was convinced I did), my bad.

Quoted 8 lines

The patch below is based on v4.1-rc7

It passes checkpatch and compiles OK

Cheers

Gab

Hi Gab,

I will try to merge your patch into next version, please help to review :)

Many thanks for your patch.
Zhou

Quoted 1,164 lines

-------------------------------------------
-------------------------------------------
This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64 on Linux 4.1-rc7.

It needs to be tested.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 242 +++++++++++++++----------------------
 drivers/pci/host/pcie-designware.h |  10 +-
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 8 files changed, 109 insertions(+), 154 deletions(-)
drivers/pci/host/pci-dra7xx.c +1 -0
index 2d57e19..5c8b6ab 100644
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
drivers/pci/host/pci-exynos.c +1 -1
index c139237..4b6db6c 100644
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-imx6.c +1 -1
index fdb9536..c4a80c5 100644
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci-keystone.c +1 -1
index 75333b0..df91f5e 100644
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +98 -144
index 2e9f84f..844febee 100644
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,16 +68,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -342,16 +334,24 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct resource_entry *win;
+	const __be32 *parser_range_end = of_get_property(np, "ranges", &rlen);
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to get
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
drivers/pci/host/pcie-designware.h +5 -5
index d0bbd27..ab78710 100644
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
drivers/pci/host/pcie-spear13xx.c +1 -3
index 020d788..e78ddf8 100644
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 661 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 3 lines · Gabriele Paoloni

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the resources associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +4 -2
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Review

Quoted 1 line
(quoted diff) +1 -0
+	const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to

get

Quoted 56 lines
drivers/pci/host/pcie-designware.c +7 -41
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	list_for_each_entry(win, &res, list) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
drivers/pci/host/pcie-designware.c +3 -6
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
Quoted 1 line

pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +3 -2
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Review

Quoted 1 line
(quoted diff) +1 -0
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
drivers/pci/host/pcie-designware.c +15 -5
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port

Quoted 7 lines
drivers/pci/host/pcie-designware.c +3 -0
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
 			int where, int size, u32 val)

{

drivers/pci/host/pcie-designware.c +1 -1
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 19 lines
drivers/pci/host/pcie-designware.c +0 -15
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 6 lines
drivers/pci/host/pcie-designware.c +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys) -{

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines
drivers/pci/host/pcie-designware.c +0 -16
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 68 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 58 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux-
pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/pci/host/pcie-designware.c +2 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 499

Quoted 8 lines
drivers/pci/host/pcie-designware.c +1 -0
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 22 lines
Quoted 22 lines
Quoted 9 lines
(quoted diff) +5 -3
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

Review int dw_pcie_host_init(struct pcie_port *pp) · line 514

Quoted 10 lines
(quoted diff) +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the

Quoted 7 lines
Quoted 7 lines

below arm64 code.

Quoted 6 lines
Quoted 4 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use

a

Quoted 8 lines
Quoted 8 lines
Quoted 2 lines

PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O

Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works as

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and arm64

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 106 lines
Quoted 106 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port *pp) · line 522

Quoted 5 lines
(quoted diff) +5 -0
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +3 -1
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines
drivers/pci/host/pcie-designware.c +1 -2
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -10
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

drivers/pci/host/pcie-designware.c +0 -8
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -8
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;

.

Quoted 11 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to majordomo at vger.kernel.org More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

.

#12 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 24 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Tuesday, June 16, 2015 12:30 PM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 3 lines · Gabriele Paoloni

Hi Zhou Wang

I apologize, I made a mistake as I didn't rebase the patch on the

latest Kernel (where I was convinced I did), my bad.

Quoted 7 lines

The patch below is based on v4.1-rc7

It passes checkpatch and compiles OK

Cheers

Quoted 8 lines
Quoted 2 lines

Gab

Hi Gab,

I will try to merge your patch into next version, please help to review :)

Sure I will :)

Thanks

Gab

Quoted 1,218 lines

Many thanks for your patch.
Zhou

Quoted 17 lines

-------------------------------------------
-------------------------------------------
This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64 on Linux 4.1-rc7.

It needs to be tested.

Quoted 7 lines
---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 242 +++++++++++++++------------

----------

drivers/pci/host/pci-

Quoted 5 lines
 drivers/pci/host/pcie-designware.h |  10 +-
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 8 files changed, 109 insertions(+), 154 deletions(-)
drivers/pci/host/pci- renamed from drivers/pci/host/pci-dra7xx.c +0 -0

dra7xx.c

drivers/pci/host/pci-dra7xx.c static int __init dra7xx_add_pcie_port(struct

Quoted 4 lines

index 2d57e19..5c8b6ab 100644

drivers/pci/host/pci-dra7xx.c +0 -0
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct

dra7xx_pcie *dra7xx,

drivers/pci/host/pci-

Quoted 8 lines
drivers/pci/host/pci-dra7xx.c +1 -0
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
drivers/pci/host/pci- renamed from drivers/pci/host/pci-exynos.c +0 -0

exynos.c

drivers/pci/host/pci-exynos.c static int __init exynos_add_pcie_port(struct

Quoted 4 lines

index c139237..4b6db6c 100644

drivers/pci/host/pci-exynos.c +0 -0
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct

pcie_port *pp,

drivers/pci/host/pci-

Quoted 9 lines
drivers/pci/host/pci-exynos.c +1 -1
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci- renamed from drivers/pci/host/pci-imx6.c +0 -0

imx6.c

drivers/pci/host/pci-imx6.c static int __init imx6_add_pcie_port(struct

Quoted 4 lines

index fdb9536..c4a80c5 100644

drivers/pci/host/pci-imx6.c +0 -0
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct

pcie_port *pp,

drivers/pci/host/pci-

Quoted 9 lines
drivers/pci/host/pci-imx6.c +1 -1
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
drivers/pci/host/pci- renamed from drivers/pci/host/pci-keystone.c +0 -0

keystone.c

drivers/pci/host/pci-keystone.c static int __init ks_add_pcie_port(struct

Quoted 4 lines

index 75333b0..df91f5e 100644

drivers/pci/host/pci-keystone.c +0 -0
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct

keystone_pcie *ks_pcie,

Review

Quoted 9 lines
drivers/pci/host/pci-keystone.c +1 -1
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
(quoted diff) +0 -0

b/drivers/pci/host/pci-layerscape.c

Review

Quoted 13 lines

index 4a6e62f..5c7a9c4 100644

drivers/pci/host/pci-layerscape.c +1 -1
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.c

Quoted 18 lines

index 2e9f84f..844febee 100644

drivers/pci/host/pcie-designware.c +1 -3
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,16 +68,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;

drivers/pci/host/pcie-designware.c line 73

Quoted 10 lines
drivers/pci/host/pcie-designware.c +1 -7
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32

*val)

drivers/pci/host/pcie-designware.c static void dw_pcie_msi_set_irq(struct pcie_port

Quoted 2 lines
drivers/pci/host/pcie-designware.c +0 -0
 {
@@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port

*pp, int irq)

drivers/pci/host/pcie-designware.c static int dw_msi_setup_irq(struct msi_controller

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller

*chip, struct pci_dev *pdev,

drivers/pci/host/pcie-designware.c static void dw_msi_teardown_irq(struct

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct

msi_controller *chip, unsigned int irq)

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -342,16 +334,24 @@ static const struct irq_domain_ops

msi_domain_ops = {

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -2
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -1
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct resource_entry *win;
+	const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to

get

Quoted 56 lines
drivers/pci/host/pcie-designware.c +7 -41
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 20 lines
drivers/pci/host/pcie-designware.c +3 -6
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
drivers/pci/host/pcie-designware.c +0 -0
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 499

Quoted 10 lines
drivers/pci/host/pcie-designware.c +3 -2
@@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 490

Quoted 1 line
drivers/pci/host/pcie-designware.c +1 -0
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 11 lines
drivers/pci/host/pcie-designware.c +3 -5
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller,

domain);

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port

Quoted 22 lines
drivers/pci/host/pcie-designware.c +12 -3
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp,

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus,

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 25 lines
drivers/pci/host/pcie-designware.c +1 -14
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 726

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -9
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
 mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys)

Quoted 9 lines
drivers/pci/host/pcie-designware.c +0 -9
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin)

Review

Quoted 21 lines
drivers/pci/host/pcie-designware.c +0 -17
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
drivers/pci/host/pcie-designware.c +0 -0
 	u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 12 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han;

Pratyush

Quoted 6 lines
Quoted 6 lines

Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 6 lines
Quoted 6 lines · Gabriele Paoloni
Quoted 3 lines

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the

resources

Quoted 262 lines
Quoted 262 lines

associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +4 -2
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
+	int rlen;
+	struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Review

Quoted 1 line
(quoted diff) +1 -0
+	const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+	if (parser_range_end == NULL)
+			return -ENOENT;
+	parser_range_end += rlen/sizeof(__be32);
+
 
 	/* Find the address cell size and the number of cells in order to

get

Quoted 56 lines
drivers/pci/host/pcie-designware.c +7 -41
 	 * the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+	if (ret)
+		return ret;
 
 	/* 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, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+	list_for_each_entry(win, &res, list) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			/* magic 5 below comes from magic na and ns in
+			 * of_pci_range_parser_init()                 */
+			pp->io_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+				ret, pp->io);
+			continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+					of_n_addr_cells(np) - 5 + na, ns);
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+			pp->cfg0_mod_base = of_read_number(parser_range_end -
+					of_n_addr_cells(np) - 5 + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
drivers/pci/host/pcie-designware.c +3 -6
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
Quoted 1 line

pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +3 -2
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
-	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+	if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
 	/* program correct class for RC */
-	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Review

Quoted 1 line
(quoted diff) +1 -0
+	if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
drivers/pci/host/pcie-designware.c +15 -5
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
 
-	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
-	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+			!= PCIBIOS_SUCCESSFUL)
+		return -EINVAL;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct

Quoted 7 lines
drivers/pci/host/pcie-designware.c +3 -0
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 11 lines
Quoted 11 lines

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus,

u32

Quoted 26 lines
Quoted 26 lines

devfn,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
 			int where, int size, u32 val)

{

drivers/pci/host/pcie-designware.c +1 -1
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -14
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
(quoted diff) +0 -1
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

drivers/pci/host/pcie-designware.c +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 88 lines
Quoted 88 lines

*sys) -{

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines
drivers/pci/host/pcie-designware.c +0 -16
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
 	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
+	resource_size_t			io_base;
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 14 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang;

Zhudacai;

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port

Quoted 8 lines
drivers/pci/host/pcie-designware.c +2 -0
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port

*pp)

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 2 lines
Quoted 2 lines

Review int dw_pcie_host_init(struct pcie_port · line 499

Quoted 2 lines
(quoted diff) +0 -0
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port · line 514

Quoted 5 lines
(quoted diff) +5 -0
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just

the

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

below arm64 code.

Quoted 2 lines
Quoted 2 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went

as

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we

use

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line
Quoted 1 line

PCIe device with a I/O Bar, it may not work well without above

code.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

But so far, I have not met a PCIe device which must work with a

I/O

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Bar.

There are two problems here:

1) the io_base address you get from

of_pci_get_host_bridge_resources

Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works

as

Quoted 11 lines
Quoted 11 lines

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and

arm64

Quoted 73 lines
Quoted 73 lines

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 57 lines
Quoted 57 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port · line 522

Quoted 5 lines
(quoted diff) +5 -0
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +3 -1
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, · line 695

Quoted 1 line
drivers/pci/host/pcie-designware.c +0 -0
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct

pci_bus

Quoted 94 lines
Quoted 79 lines
Quoted 45 lines
Quoted 45 lines

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines
drivers/pci/host/pcie-designware.c +1 -2
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -6
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -10
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

drivers/pci/host/pcie-designware.c +0 -8
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -8
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
 	u32 val;

.

Quoted 11 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to majordomo at vger.kernel.org More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

.

#13 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:

[...]

Quoted 2 lines
Quoted 2 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 505

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+   bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                         pp, &res);

I think you can't do that on ARM 32-bit platforms. They rely on pci_sys_data in pcibios_msi_controller and pcibios_align_resource, if you do not pass a pci_sys_data struct in the sysdata pointer this can't work and unless you get lucky it will explode.

We have to remove pci_sys_data dependency on ARM, then this approach will work.

Thanks,
Lorenzo

Quoted 856 lines
Quoted 855 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 5 lines
drivers/pci/host/pcie-designware.c +5 -0
+   if (!bus)
+           return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+   bus->msi = container_of(&pp->irq_domain, struct msi_controller,

domain);

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port

Quoted 22 lines
drivers/pci/host/pcie-designware.c +12 -3
+#else
+   bus->msi = &dw_pcie_msi_chip;
 #endif
 
-   dw_pci.nr_controllers = 1;
-   dw_pci.private_data = (void **)&pp;
+   pci_scan_child_bus(bus);
+   if (pp->ops->scan_bus)
+           pp->ops->scan_bus(pp);
 
-   pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+   /* support old dtbs that incorrectly describe IRQs */
+   pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+   pci_assign_unassigned_bus_resources(bus);
+   pci_bus_add_devices(bus);
 
    return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp,

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus,

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
                    int size, u32 *val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 25 lines
drivers/pci/host/pcie-designware.c +1 -14
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
                    int where, int size, u32 val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
    .write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-   struct pcie_port *pp;
-
-   pp = sys_to_pcie(sys);
-
-   if (global_io_offset < SZ_1M && pp->io_size > 0) {
-           sys->io_offset = global_io_offset - pp->io_bus_addr;
-           pci_ioremap_io(global_io_offset, pp->io_base);
-           global_io_offset += SZ_64K;
-           pci_add_resource_offset(&sys->resources, &pp->io,
-                                   sys->io_offset);
-   }

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 726

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -9
-
-   sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-   pci_add_resource_offset(&sys->resources, &pp->mem, sys-
 mem_offset);
-   pci_add_resource(&sys->resources, &pp->busn);
-
-   return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys)

Quoted 9 lines
drivers/pci/host/pcie-designware.c +0 -9
-{
-   struct pci_bus *bus;
-   struct pcie_port *pp = sys_to_pcie(sys);
-
-   pp->root_bus_nr = sys->busnr;
-   bus = pci_create_root_bus(pp->dev, sys->busnr,
-                             &dw_pcie_ops, sys, &sys->resources);
-   if (!bus)
-           return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-   pci_scan_child_bus(bus);
-
-   if (bus && pp->ops->scan_bus)
-           pp->ops->scan_bus(pp);
-
-   return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin)

Quoted 20 lines
drivers/pci/host/pcie-designware.c +0 -17
-{
-   struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-   int irq;
-
-   irq = of_irq_parse_and_map_pci(dev, slot, pin);
-   if (!irq)
-           irq = pp->irq;
-
-   return irq;
-}
-
-static struct hw_pci dw_pci = {
-   .setup          = dw_pcie_setup,
-   .scan           = dw_pcie_scan_bus,
-   .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
    u32 val;

Review

Quoted 1 line
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
    u64                     cfg1_mod_base;
    void __iomem            *va_cfg1_base;
    u32                     cfg1_size;
-   u64                     io_base;
+   resource_size_t                 io_base;
    u64                     io_mod_base;
    phys_addr_t             io_bus_addr;
    u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
    u64                     mem_mod_base;
    phys_addr_t             mem_bus_addr;
    u32                     mem_size;
-   struct resource         cfg;
-   struct resource         io;
-   struct resource         mem;
-   struct resource         busn;
+   struct resource         *cfg;
+   struct resource         *io;
+   struct resource         *mem;
+   struct resource         *busn;
    int                     irq;
    u32                     lanes;
    struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 12 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
            return ret;
    }
 
-   pp->root_bus_nr = -1;
+   pp->root_bus_nr = 0;
    pp->ops = &spear13xx_pcie_host_ops;
 
    ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han;

Pratyush

Quoted 6 lines
Quoted 6 lines

Anand; Arnd Bergmann; [email protected]; Liviu Dudau; linux- [email protected]; [email protected]; [email protected]; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 6 lines
Quoted 6 lines · Gabriele Paoloni
Quoted 3 lines

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the

resources

Quoted 262 lines
Quoted 262 lines

associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
  struct device_node *np = pp->dev->of_node;
  struct platform_device *pdev = to_platform_device(pp->dev);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +4 -2
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
  struct resource *cfg_res;
+ LIST_HEAD(res);
  u32 val, na, ns;
  const __be32 *addrp;
  int i, index, ret;
+ int rlen;
+ struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Quoted 1 line

+ const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+ if (parser_range_end == NULL)
+                 return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+
 
  /* Find the address cell size and the number of cells in order to

get

Quoted 56 lines

* the untranslated address.

drivers/pci/host/pcie-designware.c +7 -41
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
          dev_err(pp->dev, "missing *config* reg space\n");
  }
 
- if (of_pci_range_parser_init(&parser, np)) {
-         dev_err(pp->dev, "missing ranges property\n");
-         return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+ if (ret)
+         return ret;
 
  /* 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, &pp->io);
-                 pp->io.name = "I/O";
-                 pp->io.start = max_t(resource_size_t,
-                                      PCIBIOS_MIN_IO,
-                                      range.pci_addr + global_io_offset);
-                 pp->io.end = min_t(resource_size_t,
-                                    IO_SPACE_LIMIT,
-                                    range.pci_addr + range.size
-                                    + global_io_offset - 1);
-                 pp->io_size = resource_size(&pp->io);
-                 pp->io_bus_addr = range.pci_addr;
-                 pp->io_base = range.cpu_addr;
-
-                 /* Find the untranslated IO space address */
-                 pp->io_mod_base = of_read_number(parser.range -
-                                                  parser.np + na, ns);
-         }
-         if (restype == IORESOURCE_MEM) {
-                 of_pci_range_to_resource(&range, np, &pp->mem);
-                 pp->mem.name = "MEM";
-                 pp->mem_size = resource_size(&pp->mem);
-                 pp->mem_bus_addr = range.pci_addr;
-
-                 /* Find the untranslated MEM space address */
-                 pp->mem_mod_base = of_read_number(parser.range -
-                                                   parser.np + na, ns);
-         }
-         if (restype == 0) {
-                 of_pci_range_to_resource(&range, np, &pp->cfg);
-                 pp->cfg0_size = resource_size(&pp->cfg)/2;
-                 pp->cfg1_size = resource_size(&pp->cfg)/2;
-                 pp->cfg0_base = pp->cfg.start;
-                 pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+ list_for_each_entry(win, &res, list) {
+         switch (resource_type(win->res)) {
+         case IORESOURCE_IO:
+                 pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                 pp->io->name = "I/O";
+                 pp->io_size = resource_size(pp->io);
+                 pp->io_bus_addr = pp->io->start - win->offset;
+                 /* magic 5 below comes from magic na and ns in
+                  * of_pci_range_parser_init()                 */
+                 pp->io_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 ret = pci_remap_iospace(pp->io, pp->io_base);
+                 if (ret) {
+                         dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                         ret, pp->io);
+                 continue;
+                 }
+                 break;
+         case IORESOURCE_MEM:
+                 pp->mem = win->res;
+                 pp->mem->name = "MEM";
+                 pp->mem_size = resource_size(pp->mem);
+                 pp->mem_bus_addr = pp->mem->start - win->offset;
+                 pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 break;
+         case 0:
+                 pp->cfg = win->res;
+                 pp->cfg0_size = resource_size(pp->cfg)/2;
+                 pp->cfg1_size = resource_size(pp->cfg)/2;
+                 pp->cfg0_base = pp->cfg->start;
+                 pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
                  /* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-                 pp->cfg0_mod_base = of_read_number(parser.range -
-                                                    parser.np + na, ns);
-                 pp->cfg1_mod_base = pp->cfg0_mod_base +
-                                     pp->cfg0_size;
+                 pp->cfg0_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+                 break;
+         case IORESOURCE_BUS:
+                 pp->busn = win->res;
+                 break;
+         default:
+                 continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
          }
  }
 
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
-         pp->busn.name = np->name;
-         pp->busn.start = 0;
-         pp->busn.end = 0xff;
-         pp->busn.flags = IORESOURCE_BUS;
-         dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
drivers/pci/host/pcie-designware.c +3 -6
-                 ret, &pp->busn);
- }
-
  if (!pp->dbi_base) {
-         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-                                 resource_size(&pp->cfg));
+         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+                                 resource_size(pp->cfg));
          if (!pp->dbi_base) {
                  dev_err(pp->dev, "error with ioremap\n");
                  return -ENOMEM;
          }
  }
 
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
 
  if (!pp->va_cfg0_base) {
Quoted 1 line
          pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
  if (pp->ops->host_init)
          pp->ops->host_init(pp);

- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)

drivers/pci/host/pcie-designware.c +2 -1
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
  /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Quoted 1 line

+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
drivers/pci/host/pcie-designware.c +15 -5
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
  val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                       pp, &res);
+ if (!bus)
+         return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+ bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+         pp->ops->scan_bus(pp);
 
- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct

Quoted 7 lines
drivers/pci/host/pcie-designware.c +3 -0
+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);
 
  return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 11 lines
Quoted 11 lines

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
                  int size, u32 *val)
 {
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
  int ret;
 
  if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus,

u32

Quoted 26 lines
Quoted 26 lines

devfn,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
                  int where, int size, u32 val)

{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 17 lines

.write = dw_pcie_wr_conf,
};

drivers/pci/host/pcie-designware.c +0 -14
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
-         sys->io_offset = global_io_offset - pp->io_bus_addr;
-         pci_ioremap_io(global_io_offset, pp->io_base);
-         global_io_offset += SZ_64K;
-         pci_add_resource_offset(&sys->resources, &pp->io,
-                                 sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines

- pci_add_resource_offset(&sys->resources, &pp->mem, sys- mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);

drivers/pci/host/pcie-designware.c +0 -5
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 88 lines
Quoted 88 lines

*sys) -{

Quoted 8 lines

- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);

drivers/pci/host/pcie-designware.c +0 -6
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
-                           &dw_pcie_ops, sys, &sys->resources);
- if (!bus)
-         return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
- pci_scan_child_bus(bus);
-
- if (bus && pp->ops->scan_bus)
-         pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines

- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;

drivers/pci/host/pcie-designware.c +0 -14
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
-         irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup          = dw_pcie_setup,
- .scan           = dw_pcie_scan_bus,
- .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
  u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
  u64                     cfg1_mod_base;
  void __iomem            *va_cfg1_base;
  u32                     cfg1_size;
- u64                     io_base;
+ resource_size_t                 io_base;
  u64                     io_mod_base;
  phys_addr_t             io_bus_addr;
  u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
  u64                     mem_mod_base;
  phys_addr_t             mem_bus_addr;
  u32                     mem_size;
- struct resource         cfg;
- struct resource         io;
- struct resource         mem;
- struct resource         busn;
+ struct resource         *cfg;
+ struct resource         *io;
+ struct resource         *mem;
+ struct resource         *busn;
  int                     irq;
  u32                     lanes;
  struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 14 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
          return ret;
  }
 
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
  pp->ops = &spear13xx_pcie_host_ops;
 
  ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:[email protected]]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; [email protected]; Liviu Dudau; linux- [email protected]; [email protected]; [email protected]; Gabriele Paoloni; Yuanzhichang;

Zhudacai;

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
      struct device_node *np = pp->dev->of_node;
      struct platform_device *pdev = to_platform_device(pp->dev);
      struct of_pci_range range;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port

Quoted 8 lines
      struct of_pci_range_parser parser;
drivers/pci/host/pcie-designware.c +2 -0
+     struct pci_bus *bus;
      struct resource *cfg_res;
+     LIST_HEAD(res);
      u32 val, na, ns;
      const __be32 *addrp;
      int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port

*pp)

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 2 lines
Quoted 2 lines

Review int dw_pcie_host_init(struct pcie_port · line 499

Quoted 2 lines
(quoted diff) +0 -0
      val |= PORT_LOGIC_SPEED_CHANGE;
      dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-     dw_pcie_msi_chip.dev = pp->dev;
-     dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+     /*
+      * FIXME: we should really be able to use
+      * of_pci_get_host_bridge_resources on arm32 as well,
+      * but the conversion needs some more testing
+      */
+     if (global_io_offset < SZ_1M && pp->io_size > 0) {
+             pci_ioremap_io(global_io_offset, pp->io_base);
+             global_io_offset += SZ_64K;
+             pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port · line 514

Quoted 5 lines
(quoted diff) +5 -0
+                                     global_io_offset - pp->io_bus_addr);
+     }
+     pci_add_resource_offset(&res, &pp->mem,
+                             pp->mem.start - pp->mem_bus_addr);
+     pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just

the

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

below arm64 code.

Quoted 2 lines
Quoted 2 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went

as

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we

use

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line
Quoted 1 line

PCIe device with a I/O Bar, it may not work well without above

code.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

But so far, I have not met a PCIe device which must work with a

I/O

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Bar.

There are two problems here:

1) the io_base address you get from

of_pci_get_host_bridge_resources

Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works

as

Quoted 11 lines
Quoted 11 lines

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and

arm64

Quoted 73 lines
Quoted 73 lines

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+     ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 57 lines
Quoted 57 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port · line 522

Quoted 5 lines
(quoted diff) +5 -0
+     if (ret)
+             return ret;
+#endif
+
+     bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+                           pp, &res);
+     if (!bus)
+             return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+     bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+     bus->msi = &dw_pcie_msi_chip;
 #endif
 
-     dw_pci.nr_controllers = 1;
-     dw_pci.private_data = (void **)&pp;
+     pci_scan_child_bus(bus);
+     if (pp->ops->scan_bus)
+             pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +3 -1
-     pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+     /* support old dtbs that incorrectly describe IRQs */
+     pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+     pci_assign_unassigned_bus_resources(bus);
+     pci_bus_add_devices(bus);
 
      return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
                      int size, u32 *val)
 {
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, · line 695

Quoted 1 line
drivers/pci/host/pcie-designware.c +0 -0
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct

pci_bus

Quoted 94 lines
Quoted 79 lines
Quoted 45 lines
Quoted 45 lines

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines

int where, int size, u32 val)
{

drivers/pci/host/pcie-designware.c +1 -2
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
      .write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-     struct pcie_port *pp;
-
-     pp = sys_to_pcie(sys);
-

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-     if (global_io_offset < SZ_1M && pp->io_size > 0) {
-             sys->io_offset = global_io_offset - pp->io_bus_addr;
-             pci_ioremap_io(global_io_offset, pp->io_base);
-             global_io_offset += SZ_64K;
-             pci_add_resource_offset(&sys->resources, &pp->io,
-                                     sys->io_offset);
-     }
-
-     sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-     pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -6
-     pci_add_resource(&sys->resources, &pp->busn);
-
-     return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -10
-     struct pci_bus *bus;
-     struct pcie_port *pp = sys_to_pcie(sys);
-
-     pp->root_bus_nr = sys->busnr;
-     bus = pci_create_root_bus(pp->dev, sys->busnr,
-                               &dw_pcie_ops, sys, &sys->resources);
-     if (!bus)
-             return NULL;
-
-     pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-     if (bus && pp->ops->scan_bus)
-             pp->ops->scan_bus(pp);
-
-     return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

drivers/pci/host/pcie-designware.c +0 -8
-     struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-     int irq;
-
-     irq = of_irq_parse_and_map_pci(dev, slot, pin);
-     if (!irq)
-             irq = pp->irq;
-
-     return irq;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -8
-}
-
-static struct hw_pci dw_pci = {
-     .setup          = dw_pcie_setup,
-     .scan           = dw_pcie_scan_bus,
-     .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
      u32 val;

.

Quoted 11 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to [email protected] More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

.

author
#14 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 12 lines · Lorenzo Pieralisi

On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:

[...]

Quoted 2 lines
Quoted 2 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 505

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+   bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                         pp, &res);

I think you can't do that on ARM 32-bit platforms. They rely on pci_sys_data in pcibios_msi_controller and pcibios_align_resource, if you do not pass a pci_sys_data struct in the sysdata pointer this can't work and unless you get lucky it will explode.

Quoted 6 lines

We have to remove pci_sys_data dependency on ARM, then this approach will work.

Thanks,
Lorenzo

Hi Lorenzo,

For pcibios_align_resource, 1/4 can be used to solve this problem. For pcibios_msi_controller, bus->msi can be set in pcie-designware, then we can get msi controller by dev->bus->msi in pci_msi_controller.

And the latest series is v3 version
"[PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05"

Best regards,
Zhou

Quoted 859 lines
Quoted 847 lines
Quoted 847 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 5 lines
drivers/pci/host/pcie-designware.c +5 -0
+   if (!bus)
+           return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+   bus->msi = container_of(&pp->irq_domain, struct msi_controller,

domain);

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port

Quoted 22 lines
drivers/pci/host/pcie-designware.c +12 -3
+#else
+   bus->msi = &dw_pcie_msi_chip;
 #endif
 
-   dw_pci.nr_controllers = 1;
-   dw_pci.private_data = (void **)&pp;
+   pci_scan_child_bus(bus);
+   if (pp->ops->scan_bus)
+           pp->ops->scan_bus(pp);
 
-   pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+   /* support old dtbs that incorrectly describe IRQs */
+   pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+   pci_assign_unassigned_bus_resources(bus);
+   pci_bus_add_devices(bus);
 
    return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp,

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus,

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
                    int size, u32 *val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 25 lines
drivers/pci/host/pcie-designware.c +1 -14
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
                    int where, int size, u32 val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
    .write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-   struct pcie_port *pp;
-
-   pp = sys_to_pcie(sys);
-
-   if (global_io_offset < SZ_1M && pp->io_size > 0) {
-           sys->io_offset = global_io_offset - pp->io_bus_addr;
-           pci_ioremap_io(global_io_offset, pp->io_base);
-           global_io_offset += SZ_64K;
-           pci_add_resource_offset(&sys->resources, &pp->io,
-                                   sys->io_offset);
-   }

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 726

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -9
-
-   sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-   pci_add_resource_offset(&sys->resources, &pp->mem, sys-
 mem_offset);
-   pci_add_resource(&sys->resources, &pp->busn);
-
-   return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys)

Quoted 9 lines
drivers/pci/host/pcie-designware.c +0 -9
-{
-   struct pci_bus *bus;
-   struct pcie_port *pp = sys_to_pcie(sys);
-
-   pp->root_bus_nr = sys->busnr;
-   bus = pci_create_root_bus(pp->dev, sys->busnr,
-                             &dw_pcie_ops, sys, &sys->resources);
-   if (!bus)
-           return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-   pci_scan_child_bus(bus);
-
-   if (bus && pp->ops->scan_bus)
-           pp->ops->scan_bus(pp);
-
-   return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin)

Quoted 20 lines
drivers/pci/host/pcie-designware.c +0 -17
-{
-   struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-   int irq;
-
-   irq = of_irq_parse_and_map_pci(dev, slot, pin);
-   if (!irq)
-           irq = pp->irq;
-
-   return irq;
-}
-
-static struct hw_pci dw_pci = {
-   .setup          = dw_pcie_setup,
-   .scan           = dw_pcie_scan_bus,
-   .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
    u32 val;

Review

Quoted 1 line
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
    u64                     cfg1_mod_base;
    void __iomem            *va_cfg1_base;
    u32                     cfg1_size;
-   u64                     io_base;
+   resource_size_t                 io_base;
    u64                     io_mod_base;
    phys_addr_t             io_bus_addr;
    u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
    u64                     mem_mod_base;
    phys_addr_t             mem_bus_addr;
    u32                     mem_size;
-   struct resource         cfg;
-   struct resource         io;
-   struct resource         mem;
-   struct resource         busn;
+   struct resource         *cfg;
+   struct resource         *io;
+   struct resource         *mem;
+   struct resource         *busn;
    int                     irq;
    u32                     lanes;
    struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 12 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
            return ret;
    }
 
-   pp->root_bus_nr = -1;
+   pp->root_bus_nr = 0;
    pp->ops = &spear13xx_pcie_host_ops;
 
    ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han;

Pratyush

Quoted 6 lines
Quoted 6 lines

Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 6 lines
Quoted 6 lines · Gabriele Paoloni
Quoted 3 lines

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the

resources

Quoted 262 lines
Quoted 262 lines

associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
  struct device_node *np = pp->dev->of_node;
  struct platform_device *pdev = to_platform_device(pp->dev);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +4 -2
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
  struct resource *cfg_res;
+ LIST_HEAD(res);
  u32 val, na, ns;
  const __be32 *addrp;
  int i, index, ret;
+ int rlen;
+ struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Quoted 1 line

+ const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+ if (parser_range_end == NULL)
+                 return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+
 
  /* Find the address cell size and the number of cells in order to

get

Quoted 56 lines

* the untranslated address.

drivers/pci/host/pcie-designware.c +7 -41
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
          dev_err(pp->dev, "missing *config* reg space\n");
  }
 
- if (of_pci_range_parser_init(&parser, np)) {
-         dev_err(pp->dev, "missing ranges property\n");
-         return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+ if (ret)
+         return ret;
 
  /* 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, &pp->io);
-                 pp->io.name = "I/O";
-                 pp->io.start = max_t(resource_size_t,
-                                      PCIBIOS_MIN_IO,
-                                      range.pci_addr + global_io_offset);
-                 pp->io.end = min_t(resource_size_t,
-                                    IO_SPACE_LIMIT,
-                                    range.pci_addr + range.size
-                                    + global_io_offset - 1);
-                 pp->io_size = resource_size(&pp->io);
-                 pp->io_bus_addr = range.pci_addr;
-                 pp->io_base = range.cpu_addr;
-
-                 /* Find the untranslated IO space address */
-                 pp->io_mod_base = of_read_number(parser.range -
-                                                  parser.np + na, ns);
-         }
-         if (restype == IORESOURCE_MEM) {
-                 of_pci_range_to_resource(&range, np, &pp->mem);
-                 pp->mem.name = "MEM";
-                 pp->mem_size = resource_size(&pp->mem);
-                 pp->mem_bus_addr = range.pci_addr;
-
-                 /* Find the untranslated MEM space address */
-                 pp->mem_mod_base = of_read_number(parser.range -
-                                                   parser.np + na, ns);
-         }
-         if (restype == 0) {
-                 of_pci_range_to_resource(&range, np, &pp->cfg);
-                 pp->cfg0_size = resource_size(&pp->cfg)/2;
-                 pp->cfg1_size = resource_size(&pp->cfg)/2;
-                 pp->cfg0_base = pp->cfg.start;
-                 pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+ list_for_each_entry(win, &res, list) {
+         switch (resource_type(win->res)) {
+         case IORESOURCE_IO:
+                 pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                 pp->io->name = "I/O";
+                 pp->io_size = resource_size(pp->io);
+                 pp->io_bus_addr = pp->io->start - win->offset;
+                 /* magic 5 below comes from magic na and ns in
+                  * of_pci_range_parser_init()                 */
+                 pp->io_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 ret = pci_remap_iospace(pp->io, pp->io_base);
+                 if (ret) {
+                         dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                         ret, pp->io);
+                 continue;
+                 }
+                 break;
+         case IORESOURCE_MEM:
+                 pp->mem = win->res;
+                 pp->mem->name = "MEM";
+                 pp->mem_size = resource_size(pp->mem);
+                 pp->mem_bus_addr = pp->mem->start - win->offset;
+                 pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 break;
+         case 0:
+                 pp->cfg = win->res;
+                 pp->cfg0_size = resource_size(pp->cfg)/2;
+                 pp->cfg1_size = resource_size(pp->cfg)/2;
+                 pp->cfg0_base = pp->cfg->start;
+                 pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
                  /* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-                 pp->cfg0_mod_base = of_read_number(parser.range -
-                                                    parser.np + na, ns);
-                 pp->cfg1_mod_base = pp->cfg0_mod_base +
-                                     pp->cfg0_size;
+                 pp->cfg0_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+                 break;
+         case IORESOURCE_BUS:
+                 pp->busn = win->res;
+                 break;
+         default:
+                 continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
          }
  }
 
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
-         pp->busn.name = np->name;
-         pp->busn.start = 0;
-         pp->busn.end = 0xff;
-         pp->busn.flags = IORESOURCE_BUS;
-         dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
drivers/pci/host/pcie-designware.c +3 -6
-                 ret, &pp->busn);
- }
-
  if (!pp->dbi_base) {
-         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-                                 resource_size(&pp->cfg));
+         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+                                 resource_size(pp->cfg));
          if (!pp->dbi_base) {
                  dev_err(pp->dev, "error with ioremap\n");
                  return -ENOMEM;
          }
  }
 
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
 
  if (!pp->va_cfg0_base) {
Quoted 1 line
          pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
  if (pp->ops->host_init)
          pp->ops->host_init(pp);

- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)

drivers/pci/host/pcie-designware.c +2 -1
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
  /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Quoted 1 line

+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
drivers/pci/host/pcie-designware.c +15 -5
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
  val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                       pp, &res);
+ if (!bus)
+         return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+ bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+         pp->ops->scan_bus(pp);
 
- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct

Quoted 7 lines
drivers/pci/host/pcie-designware.c +3 -0
+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);
 
  return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 11 lines
Quoted 11 lines

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
                  int size, u32 *val)
 {
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
  int ret;
 
  if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus,

u32

Quoted 26 lines
Quoted 26 lines

devfn,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
                  int where, int size, u32 val)

{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 17 lines

.write = dw_pcie_wr_conf,
};

drivers/pci/host/pcie-designware.c +0 -14
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
-         sys->io_offset = global_io_offset - pp->io_bus_addr;
-         pci_ioremap_io(global_io_offset, pp->io_base);
-         global_io_offset += SZ_64K;
-         pci_add_resource_offset(&sys->resources, &pp->io,
-                                 sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines

- pci_add_resource_offset(&sys->resources, &pp->mem, sys- mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);

drivers/pci/host/pcie-designware.c +0 -5
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 88 lines
Quoted 88 lines

*sys) -{

Quoted 8 lines

- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);

drivers/pci/host/pcie-designware.c +0 -6
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
-                           &dw_pcie_ops, sys, &sys->resources);
- if (!bus)
-         return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
- pci_scan_child_bus(bus);
-
- if (bus && pp->ops->scan_bus)
-         pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines

- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;

drivers/pci/host/pcie-designware.c +0 -14
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
-         irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup          = dw_pcie_setup,
- .scan           = dw_pcie_scan_bus,
- .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
  u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
  u64                     cfg1_mod_base;
  void __iomem            *va_cfg1_base;
  u32                     cfg1_size;
- u64                     io_base;
+ resource_size_t                 io_base;
  u64                     io_mod_base;
  phys_addr_t             io_bus_addr;
  u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
  u64                     mem_mod_base;
  phys_addr_t             mem_bus_addr;
  u32                     mem_size;
- struct resource         cfg;
- struct resource         io;
- struct resource         mem;
- struct resource         busn;
+ struct resource         *cfg;
+ struct resource         *io;
+ struct resource         *mem;
+ struct resource         *busn;
  int                     irq;
  u32                     lanes;
  struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 14 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
          return ret;
  }
 
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
  pp->ops = &spear13xx_pcie_host_ops;
 
  ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang;

Zhudacai;

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
      struct device_node *np = pp->dev->of_node;
      struct platform_device *pdev = to_platform_device(pp->dev);
      struct of_pci_range range;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port

Quoted 8 lines
      struct of_pci_range_parser parser;
drivers/pci/host/pcie-designware.c +2 -0
+     struct pci_bus *bus;
      struct resource *cfg_res;
+     LIST_HEAD(res);
      u32 val, na, ns;
      const __be32 *addrp;
      int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port

*pp)

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 2 lines
Quoted 2 lines

Review int dw_pcie_host_init(struct pcie_port · line 499

Quoted 2 lines
(quoted diff) +0 -0
      val |= PORT_LOGIC_SPEED_CHANGE;
      dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-     dw_pcie_msi_chip.dev = pp->dev;
-     dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+     /*
+      * FIXME: we should really be able to use
+      * of_pci_get_host_bridge_resources on arm32 as well,
+      * but the conversion needs some more testing
+      */
+     if (global_io_offset < SZ_1M && pp->io_size > 0) {
+             pci_ioremap_io(global_io_offset, pp->io_base);
+             global_io_offset += SZ_64K;
+             pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port · line 514

Quoted 5 lines
(quoted diff) +5 -0
+                                     global_io_offset - pp->io_bus_addr);
+     }
+     pci_add_resource_offset(&res, &pp->mem,
+                             pp->mem.start - pp->mem_bus_addr);
+     pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just

the

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

below arm64 code.

Quoted 2 lines
Quoted 2 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went

as

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we

use

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line
Quoted 1 line

PCIe device with a I/O Bar, it may not work well without above

code.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

But so far, I have not met a PCIe device which must work with a

I/O

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Bar.

There are two problems here:

1) the io_base address you get from

of_pci_get_host_bridge_resources

Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works

as

Quoted 11 lines
Quoted 11 lines

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and

arm64

Quoted 73 lines
Quoted 73 lines

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+     ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 57 lines
Quoted 57 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port · line 522

Quoted 5 lines
(quoted diff) +5 -0
+     if (ret)
+             return ret;
+#endif
+
+     bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+                           pp, &res);
+     if (!bus)
+             return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+     bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+     bus->msi = &dw_pcie_msi_chip;
 #endif
 
-     dw_pci.nr_controllers = 1;
-     dw_pci.private_data = (void **)&pp;
+     pci_scan_child_bus(bus);
+     if (pp->ops->scan_bus)
+             pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +3 -1
-     pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+     /* support old dtbs that incorrectly describe IRQs */
+     pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+     pci_assign_unassigned_bus_resources(bus);
+     pci_bus_add_devices(bus);
 
      return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
                      int size, u32 *val)
 {
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, · line 695

Quoted 1 line
drivers/pci/host/pcie-designware.c +0 -0
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct

pci_bus

Quoted 87 lines
Quoted 87 lines
Quoted 45 lines
Quoted 45 lines

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines

int where, int size, u32 val)
{

drivers/pci/host/pcie-designware.c +1 -2
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
      .write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-     struct pcie_port *pp;
-
-     pp = sys_to_pcie(sys);
-

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-     if (global_io_offset < SZ_1M && pp->io_size > 0) {
-             sys->io_offset = global_io_offset - pp->io_bus_addr;
-             pci_ioremap_io(global_io_offset, pp->io_base);
-             global_io_offset += SZ_64K;
-             pci_add_resource_offset(&sys->resources, &pp->io,
-                                     sys->io_offset);
-     }
-
-     sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-     pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -6
-     pci_add_resource(&sys->resources, &pp->busn);
-
-     return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -10
-     struct pci_bus *bus;
-     struct pcie_port *pp = sys_to_pcie(sys);
-
-     pp->root_bus_nr = sys->busnr;
-     bus = pci_create_root_bus(pp->dev, sys->busnr,
-                               &dw_pcie_ops, sys, &sys->resources);
-     if (!bus)
-             return NULL;
-
-     pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-     if (bus && pp->ops->scan_bus)
-             pp->ops->scan_bus(pp);
-
-     return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

drivers/pci/host/pcie-designware.c +0 -8
-     struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-     int irq;
-
-     irq = of_irq_parse_and_map_pci(dev, slot, pin);
-     if (!irq)
-             irq = pp->irq;
-
-     return irq;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -8
-}
-
-static struct hw_pci dw_pci = {
-     .setup          = dw_pcie_setup,
-     .scan           = dw_pcie_scan_bus,
-     .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
      u32 val;

.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to majordomo at vger.kernel.org More

majordomo

Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

Quoted 9 lines
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
Quoted 2 lines

.

.

.

#15 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 20 lines · Zhou Wang
Quoted 12 lines · Lorenzo Pieralisi

On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:

[...]

Quoted 2 lines
Quoted 2 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 505

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+   bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                         pp, &res);

I think you can't do that on ARM 32-bit platforms. They rely on pci_sys_data in pcibios_msi_controller and pcibios_align_resource, if you do not pass a pci_sys_data struct in the sysdata pointer this can't work and unless you get lucky it will explode.

Quoted 6 lines

We have to remove pci_sys_data dependency on ARM, then this approach will work.

Thanks,
Lorenzo

Quoted 5 lines

Hi Lorenzo,

For pcibios_align_resource, 1/4 can be used to solve this problem. For pcibios_msi_controller, bus->msi can be set in pcie-designware, then we can get msi controller by dev->bus->msi in pci_msi_controller.

Yes, 1/4 solves the problem I know, but that's a bit hackish, it would be better if we can create the host bridge and pass it to create_root_bus, that's what Yijing was doing but I am not sure if that's still the plan given his latest series here.

https://patchwork.ozlabs.org/project/linux-pci/list/?submitter=15928

I've just posted a patch for pcibios_msi_controller removal, I did not notice that it was something already put forward by Arnd, anyway those are the last two steps required, let's get them merged.

https://patchwork.ozlabs.org/patch/494498/

Lorenzo

Quoted 872 lines

And the latest series is v3 version
"[PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05"

Best regards,
Zhou

Quoted 852 lines
Quoted 852 lines
Quoted 852 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 5 lines
drivers/pci/host/pcie-designware.c +5 -0
+   if (!bus)
+           return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+   bus->msi = container_of(&pp->irq_domain, struct msi_controller,

domain);

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port

Quoted 22 lines
drivers/pci/host/pcie-designware.c +12 -3
+#else
+   bus->msi = &dw_pcie_msi_chip;
 #endif
 
-   dw_pci.nr_controllers = 1;
-   dw_pci.private_data = (void **)&pp;
+   pci_scan_child_bus(bus);
+   if (pp->ops->scan_bus)
+           pp->ops->scan_bus(pp);
 
-   pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+   /* support old dtbs that incorrectly describe IRQs */
+   pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+   pci_assign_unassigned_bus_resources(bus);
+   pci_bus_add_devices(bus);
 
    return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port

*pp,

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus,

Quoted 9 lines
drivers/pci/host/pcie-designware.c +1 -1
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
                    int size, u32 *val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 25 lines
drivers/pci/host/pcie-designware.c +1 -14
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
                    int where, int size, u32 val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
    .write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-   struct pcie_port *pp;
-
-   pp = sys_to_pcie(sys);
-
-   if (global_io_offset < SZ_1M && pp->io_size > 0) {
-           sys->io_offset = global_io_offset - pp->io_bus_addr;
-           pci_ioremap_io(global_io_offset, pp->io_base);
-           global_io_offset += SZ_64K;
-           pci_add_resource_offset(&sys->resources, &pp->io,
-                                   sys->io_offset);
-   }

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 726

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -9
-
-   sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-   pci_add_resource_offset(&sys->resources, &pp->mem, sys-
 mem_offset);
-   pci_add_resource(&sys->resources, &pp->busn);
-
-   return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data

*sys)

Quoted 9 lines
drivers/pci/host/pcie-designware.c +0 -9
-{
-   struct pci_bus *bus;
-   struct pcie_port *pp = sys_to_pcie(sys);
-
-   pp->root_bus_nr = sys->busnr;
-   bus = pci_create_root_bus(pp->dev, sys->busnr,
-                             &dw_pcie_ops, sys, &sys->resources);
-   if (!bus)
-           return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
-   pci_scan_child_bus(bus);
-
-   if (bus && pp->ops->scan_bus)
-           pp->ops->scan_bus(pp);
-
-   return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin)

Quoted 20 lines
drivers/pci/host/pcie-designware.c +0 -17
-{
-   struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-   int irq;
-
-   irq = of_irq_parse_and_map_pci(dev, slot, pin);
-   if (!irq)
-           irq = pp->irq;
-
-   return irq;
-}
-
-static struct hw_pci dw_pci = {
-   .setup          = dw_pcie_setup,
-   .scan           = dw_pcie_scan_bus,
-   .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
    u32 val;

Review

Quoted 1 line
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
    u64                     cfg1_mod_base;
    void __iomem            *va_cfg1_base;
    u32                     cfg1_size;
-   u64                     io_base;
+   resource_size_t                 io_base;
    u64                     io_mod_base;
    phys_addr_t             io_bus_addr;
    u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
    u64                     mem_mod_base;
    phys_addr_t             mem_bus_addr;
    u32                     mem_size;
-   struct resource         cfg;
-   struct resource         io;
-   struct resource         mem;
-   struct resource         busn;
+   struct resource         *cfg;
+   struct resource         *io;
+   struct resource         *mem;
+   struct resource         *busn;
    int                     irq;
    u32                     lanes;
    struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 12 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
            return ret;
    }
 
-   pp->root_bus_nr = -1;
+   pp->root_bus_nr = 0;
    pp->ops = &spear13xx_pcie_host_ops;
 
    ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han;

Pratyush

Quoted 6 lines
Quoted 6 lines

Anand; Arnd Bergmann; [email protected]; Liviu Dudau; linux- [email protected]; [email protected]; [email protected]; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 6 lines
Quoted 6 lines · Gabriele Paoloni
Quoted 3 lines

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can see I

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the

resources

Quoted 262 lines
Quoted 262 lines

associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port pp,

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]"; so I

have also included all the changes about the other drivers

Quoted 15 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou Wang.

Quoted 7 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is gone.

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some format errors
about this patch. And I think this patch is a experimental one, it could not
be compiled successfully.

Quoted 12 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
  struct device_node *np = pp->dev->of_node;
  struct platform_device *pdev = to_platform_device(pp->dev);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +4 -2
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
  struct resource *cfg_res;
+ LIST_HEAD(res);
  u32 val, na, ns;
  const __be32 *addrp;
  int i, index, ret;
+ int rlen;
+ struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use struct resource_entry.

Thanks,
Zhou

Quoted 1 line

+ const __be32 *parser_range_end = of_get_property(np, "ranges",

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+ if (parser_range_end == NULL)
+                 return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+
 
  /* Find the address cell size and the number of cells in order to

get

Quoted 56 lines

* the untranslated address.

drivers/pci/host/pcie-designware.c +7 -41
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
          dev_err(pp->dev, "missing *config* reg space\n");
  }
 
- if (of_pci_range_parser_init(&parser, np)) {
-         dev_err(pp->dev, "missing ranges property\n");
-         return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
 io_base);
+ if (ret)
+         return ret;
 
  /* 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, &pp->io);
-                 pp->io.name = "I/O";
-                 pp->io.start = max_t(resource_size_t,
-                                      PCIBIOS_MIN_IO,
-                                      range.pci_addr + global_io_offset);
-                 pp->io.end = min_t(resource_size_t,
-                                    IO_SPACE_LIMIT,
-                                    range.pci_addr + range.size
-                                    + global_io_offset - 1);
-                 pp->io_size = resource_size(&pp->io);
-                 pp->io_bus_addr = range.pci_addr;
-                 pp->io_base = range.cpu_addr;
-
-                 /* Find the untranslated IO space address */
-                 pp->io_mod_base = of_read_number(parser.range -
-                                                  parser.np + na, ns);
-         }
-         if (restype == IORESOURCE_MEM) {
-                 of_pci_range_to_resource(&range, np, &pp->mem);
-                 pp->mem.name = "MEM";
-                 pp->mem_size = resource_size(&pp->mem);
-                 pp->mem_bus_addr = range.pci_addr;
-
-                 /* Find the untranslated MEM space address */
-                 pp->mem_mod_base = of_read_number(parser.range -
-                                                   parser.np + na, ns);
-         }
-         if (restype == 0) {
-                 of_pci_range_to_resource(&range, np, &pp->cfg);
-                 pp->cfg0_size = resource_size(&pp->cfg)/2;
-                 pp->cfg1_size = resource_size(&pp->cfg)/2;
-                 pp->cfg0_base = pp->cfg.start;
-                 pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+ list_for_each_entry(win, &res, list) {
+         switch (resource_type(win->res)) {
+         case IORESOURCE_IO:
+                 pp->io = win->res;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 397

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                 pp->io->name = "I/O";
+                 pp->io_size = resource_size(pp->io);
+                 pp->io_bus_addr = pp->io->start - win->offset;
+                 /* magic 5 below comes from magic na and ns in
+                  * of_pci_range_parser_init()                 */
+                 pp->io_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 ret = pci_remap_iospace(pp->io, pp->io_base);
+                 if (ret) {
+                         dev_warn(pp->dev, "error %d: failed to map

resource %pR\n",

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+                         ret, pp->io);
+                 continue;
+                 }
+                 break;
+         case IORESOURCE_MEM:
+                 pp->mem = win->res;
+                 pp->mem->name = "MEM";
+                 pp->mem_size = resource_size(pp->mem);
+                 pp->mem_bus_addr = pp->mem->start - win->offset;
+                 pp->mem_mod_base = of_read_number(parser_range_end -

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -0
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 break;
+         case 0:
+                 pp->cfg = win->res;
+                 pp->cfg0_size = resource_size(pp->cfg)/2;
+                 pp->cfg1_size = resource_size(pp->cfg)/2;
+                 pp->cfg0_base = pp->cfg->start;
+                 pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
 
                  /* Find the untranslated configuration space address

*/

Quoted 13 lines
drivers/pci/host/pcie-designware.c +9 -4
-                 pp->cfg0_mod_base = of_read_number(parser.range -
-                                                    parser.np + na, ns);
-                 pp->cfg1_mod_base = pp->cfg0_mod_base +
-                                     pp->cfg0_size;
+                 pp->cfg0_mod_base = of_read_number(parser_range_end -
+                                 of_n_addr_cells(np) - 5 + na, ns);
+                 pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+                 break;
+         case IORESOURCE_BUS:
+                 pp->busn = win->res;
+                 break;
+         default:
+                 continue;

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
          }
  }
 
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
-         pp->busn.name = np->name;
-         pp->busn.start = 0;
-         pp->busn.end = 0xff;
-         pp->busn.flags = IORESOURCE_BUS;
-         dev_dbg(pp->dev, "failed to parse bus-range property: %d,

using default %pR\n",

Quoted 18 lines
drivers/pci/host/pcie-designware.c +3 -6
-                 ret, &pp->busn);
- }
-
  if (!pp->dbi_base) {
-         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-                                 resource_size(&pp->cfg));
+         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+                                 resource_size(pp->cfg));
          if (!pp->dbi_base) {
                  dev_err(pp->dev, "error with ioremap\n");
                  return -ENOMEM;
          }
  }
 
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
 
  if (!pp->va_cfg0_base) {
Quoted 1 line
          pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
  if (pp->ops->host_init)
          pp->ops->host_init(pp);

- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)

drivers/pci/host/pcie-designware.c +2 -1
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
  /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Quoted 1 line

+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 25 lines
drivers/pci/host/pcie-designware.c +15 -5
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
  val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                       pp, &res);
+ if (!bus)
+         return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct msi_controller,
+domain); #else
+ bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+         pp->ops->scan_bus(pp);
 
- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct

Quoted 7 lines
drivers/pci/host/pcie-designware.c +3 -0
+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);
 
  return 0;
 }
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 11 lines
Quoted 11 lines

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct pcie_port *pp,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
                  int size, u32 *val)
 {
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
  int ret;
 
  if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { @@ -

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct pci_bus *bus,

u32

Quoted 26 lines
Quoted 26 lines

devfn,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
                  int where, int size, u32 val)

{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@ -

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 17 lines

.write = dw_pcie_wr_conf,
};

drivers/pci/host/pcie-designware.c +0 -14
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
-         sys->io_offset = global_io_offset - pp->io_bus_addr;
-         pci_ioremap_io(global_io_offset, pp->io_base);
-         global_io_offset += SZ_64K;
-         pci_add_resource_offset(&sys->resources, &pp->io,
-                                 sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines

- pci_add_resource_offset(&sys->resources, &pp->mem, sys- mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);

drivers/pci/host/pcie-designware.c +0 -5
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 88 lines
Quoted 88 lines

*sys) -{

Quoted 8 lines

- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);

drivers/pci/host/pcie-designware.c +0 -6
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
-                           &dw_pcie_ops, sys, &sys->resources);
- if (!bus)
-         return NULL;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-
- pci_scan_child_bus(bus);
-
- if (bus && pp->ops->scan_bus)
-         pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8

pin) -{

Review

Quoted 19 lines

- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;

drivers/pci/host/pcie-designware.c +0 -14
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
-         irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup          = dw_pcie_setup,
- .scan           = dw_pcie_scan_bus,
- .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
  u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
  u64                     cfg1_mod_base;
  void __iomem            *va_cfg1_base;
  u32                     cfg1_size;
- u64                     io_base;
+ resource_size_t                 io_base;
  u64                     io_mod_base;
  phys_addr_t             io_bus_addr;
  u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
  u64                     mem_mod_base;
  phys_addr_t             mem_bus_addr;
  u32                     mem_size;
- struct resource         cfg;
- struct resource         io;
- struct resource         mem;
- struct resource         busn;
+ struct resource         *cfg;
+ struct resource         *io;
+ struct resource         *mem;
+ struct resource         *busn;
  int                     irq;
  u32                     lanes;
  struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 14 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
          return ret;
  }
 
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
  pp->ops = &spear13xx_pcie_host_ops;
 
  ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:[email protected]]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; [email protected]; Liviu Dudau; linux- [email protected]; [email protected]; [email protected]; Gabriele Paoloni; Yuanzhichang;

Zhudacai;

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
      struct device_node *np = pp->dev->of_node;
      struct platform_device *pdev = to_platform_device(pp->dev);
      struct of_pci_range range;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port

Quoted 8 lines
      struct of_pci_range_parser parser;
drivers/pci/host/pcie-designware.c +2 -0
+     struct pci_bus *bus;
      struct resource *cfg_res;
+     LIST_HEAD(res);
      u32 val, na, ns;
      const __be32 *addrp;
      int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port

*pp)

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 2 lines
Quoted 2 lines

Review int dw_pcie_host_init(struct pcie_port · line 499

Quoted 2 lines
(quoted diff) +0 -0
      val |= PORT_LOGIC_SPEED_CHANGE;
      dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
(quoted diff) +10 -3
-#ifdef CONFIG_PCI_MSI
-     dw_pcie_msi_chip.dev = pp->dev;
-     dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+     /*
+      * FIXME: we should really be able to use
+      * of_pci_get_host_bridge_resources on arm32 as well,
+      * but the conversion needs some more testing
+      */
+     if (global_io_offset < SZ_1M && pp->io_size > 0) {
+             pci_ioremap_io(global_io_offset, pp->io_base);
+             global_io_offset += SZ_64K;
+             pci_add_resource_offset(&res, &pp->io,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review int dw_pcie_host_init(struct pcie_port · line 514

Quoted 5 lines
(quoted diff) +5 -0
+                                     global_io_offset - pp->io_bus_addr);
+     }
+     pci_add_resource_offset(&res, &pp->mem,
+                             pp->mem.start - pp->mem_bus_addr);
+     pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just

the

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

below arm64 code.

Quoted 2 lines
Quoted 2 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went

as

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we

use

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line
Quoted 1 line

PCIe device with a I/O Bar, it may not work well without above

code.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

But so far, I have not met a PCIe device which must work with a

I/O

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Bar.

There are two problems here:

1) the io_base address you get from

of_pci_get_host_bridge_resources

Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

must be mapped using pci_remap_iospace. You are not doing this,

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work on

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64 works

as

Quoted 11 lines
Quoted 11 lines

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the value

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and

arm64

Quoted 73 lines
Quoted 73 lines

so,

Quoted 8 lines
Quoted 8 lines

as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Review int dw_pcie_host_init(struct pcie_port · line 517

Quoted 3 lines
(quoted diff) +3 -0
+#else
+     ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning

on

Quoted 57 lines
Quoted 57 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct pcie_port · line 522

Quoted 5 lines
(quoted diff) +5 -0
+     if (ret)
+             return ret;
+#endif
+
+     bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+                           pp, &res);
+     if (!bus)
+             return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+     bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+     bus->msi = &dw_pcie_msi_chip;
 #endif
 
-     dw_pci.nr_controllers = 1;
-     dw_pci.private_data = (void **)&pp;
+     pci_scan_child_bus(bus);
+     if (pp->ops->scan_bus)
+             pp->ops->scan_bus(pp);
 
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +3 -1
-     pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+     /* support old dtbs that incorrectly describe IRQs */
+     pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_valid_config(struct · line 683

Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+     pci_assign_unassigned_bus_resources(bus);
+     pci_bus_add_devices(bus);
 
      return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct
 pcie_port *pp,  static int dw_pcie_rd_conf(struct pci_bus *bus,

u32 devfn, int where,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1 -1
                      int size, u32 *val)
 {
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, · line 695

Quoted 1 line
drivers/pci/host/pcie-designware.c +0 -0
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, static int dw_pcie_wr_conf(struct

pci_bus

Quoted 92 lines
Quoted 90 lines
Quoted 45 lines
Quoted 45 lines

*bus, u32 devfn,

Quoted 44 lines
Quoted 11 lines
Quoted 11 lines

int where, int size, u32 val)
{

drivers/pci/host/pcie-designware.c +1 -2
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@
-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
      .write = dw_pcie_wr_conf,
 };
Quoted 15 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
-     struct pcie_port *pp;
-
-     pp = sys_to_pcie(sys);
-

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -10
-     if (global_io_offset < SZ_1M && pp->io_size > 0) {
-             sys->io_offset = global_io_offset - pp->io_bus_addr;
-             pci_ioremap_io(global_io_offset, pp->io_base);
-             global_io_offset += SZ_64K;
-             pci_add_resource_offset(&sys->resources, &pp->io,
-                                     sys->io_offset);
-     }
-
-     sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-     pci_add_resource_offset(&sys->resources, &pp->mem, sys-

mem_offset);

Quoted 17 lines
Quoted 17 lines
drivers/pci/host/pcie-designware.c +0 -6
-     pci_add_resource(&sys->resources, &pp->busn);
-
-     return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -10
-     struct pci_bus *bus;
-     struct pcie_port *pp = sys_to_pcie(sys);
-
-     pp->root_bus_nr = sys->busnr;
-     bus = pci_create_root_bus(pp->dev, sys->busnr,
-                               &dw_pcie_ops, sys, &sys->resources);
-     if (!bus)
-             return NULL;
-
-     pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-     if (bus && pp->ops->scan_bus)
-             pp->ops->scan_bus(pp);
-
-     return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 23 lines
Quoted 9 lines

pin) -{

drivers/pci/host/pcie-designware.c +0 -8
-     struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-     int irq;
-
-     irq = of_irq_parse_and_map_pci(dev, slot, pin);
-     if (!irq)
-             irq = pp->irq;
-
-     return irq;

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -8
-}
-
-static struct hw_pci dw_pci = {
-     .setup          = dw_pcie_setup,
-     .scan           = dw_pcie_scan_bus,
-     .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
      u32 val;

.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to [email protected] More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines

.

.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#16 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Quoted 41 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Monday, July 13, 2015 3:18 PM
To: Wangzhou (B)
Cc: Gabriele Paoloni; James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 6 lines · Zhou Wang
Quoted 5 lines · Lorenzo Pieralisi

On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:

[...]

Quoted 1 line
Quoted 1 line
Quoted 1 line

+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line

+ pp, &res);

I think you can't do that on ARM 32-bit platforms. They rely on

pci_sys_data

Quoted 2 lines
Quoted 2 lines

in pcibios_msi_controller and pcibios_align_resource, if you do not pass a pci_sys_data struct in the sysdata pointer this can't work

and

Quoted 3 lines
Quoted 3 lines

unless you get lucky it will explode.

We have to remove pci_sys_data dependency on ARM, then this

approach

Quoted 10 lines
Quoted 5 lines

will work.

Thanks,
Lorenzo

Hi Lorenzo,

For pcibios_align_resource, 1/4 can be used to solve this problem. For pcibios_msi_controller, bus->msi can be set in pcie-designware,

then

Quoted 8 lines
Quoted 1 line

we can get msi controller by dev->bus->msi in pci_msi_controller.

Yes, 1/4 solves the problem I know, but that's a bit hackish, it would be better if we can create the host bridge and pass it to create_root_bus, that's what Yijing was doing but I am not sure if that's still the plan given his latest series here.

https://patchwork.ozlabs.org/project/linux-pci/list/?submitter=15928

I have submitted a new patch for this:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/357431.html

Quoted 980 lines

I've just posted a patch for pcibios_msi_controller removal, I did not notice that it was something already put forward by Arnd, anyway those are the last two steps required, let's get them merged.

https://patchwork.ozlabs.org/patch/494498/

Lorenzo

Quoted 2 lines

And the latest series is v3 version
"[PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc

Hip05"

Quoted 9 lines

Best regards,
Zhou

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 5 lines
drivers/pci/host/pcie-designware.c +5 -0
+   if (!bus)
+           return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+   bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 20 lines
Quoted 20 lines
Quoted 20 lines
Quoted 20 lines

domain);

Quoted 19 lines
drivers/pci/host/pcie-designware.c +12 -3
+#else
+   bus->msi = &dw_pcie_msi_chip;
 #endif
 
-   dw_pci.nr_controllers = 1;
-   dw_pci.private_data = (void **)&pp;
+   pci_scan_child_bus(bus);
+   if (pp->ops->scan_bus)
+           pp->ops->scan_bus(pp);
 
-   pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+   /* support old dtbs that incorrectly describe IRQs */
+   pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+   pci_assign_unassigned_bus_resources(bus);
+   pci_bus_add_devices(bus);
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Review static int dw_pcie_valid_config(struct

Quoted 3 lines
    return 0;

}

(quoted diff) +0 -0
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

*pp,

Quoted 1 line
(quoted diff) +0 -0
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int

where,

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static int dw_pcie_rd_conf(struct pci_bus

Quoted 8 lines
drivers/pci/host/pcie-designware.c +1 -1
                    int size, u32 *val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus

*bus,

Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines

u32 devfn, int where,

Quoted 27 lines
drivers/pci/host/pcie-designware.c +1 -16
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
                    int where, int size, u32 val)
 {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+   struct pcie_port *pp = bus->sysdata;
    int ret;
 
    if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
    .write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-   struct pcie_port *pp;
-
-   pp = sys_to_pcie(sys);
-
-   if (global_io_offset < SZ_1M && pp->io_size > 0) {
-           sys->io_offset = global_io_offset - pp->io_bus_addr;
-           pci_ioremap_io(global_io_offset, pp->io_base);
-           global_io_offset += SZ_64K;
-           pci_add_resource_offset(&sys->resources, &pp->io,
-                                   sys->io_offset);
-   }
-
-   sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -7
-   pci_add_resource_offset(&sys->resources, &pp->mem, sys-
 mem_offset);
-   pci_add_resource(&sys->resources, &pp->busn);
-
-   return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 9 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

*sys)

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -7
-{
-   struct pci_bus *bus;
-   struct pcie_port *pp = sys_to_pcie(sys);
-
-   pp->root_bus_nr = sys->busnr;
-   bus = pci_create_root_bus(pp->dev, sys->busnr,
-                             &dw_pcie_ops, sys, &sys-

resources);

Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/pci/host/pcie-designware.c +0 -4
-   if (!bus)
-           return NULL;
-
-   pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-   if (bus && pp->ops->scan_bus)
-           pp->ops->scan_bus(pp);
-
-   return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
Quoted 69 lines

pin)

Quoted 20 lines
drivers/pci/host/pcie-designware.c +0 -17
-{
-   struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-   int irq;
-
-   irq = of_irq_parse_and_map_pci(dev, slot, pin);
-   if (!irq)
-           irq = pp->irq;
-
-   return irq;
-}
-
-static struct hw_pci dw_pci = {
-   .setup          = dw_pcie_setup,
-   .scan           = dw_pcie_scan_bus,
-   .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
    u32 val;

Review

Quoted 1 line
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
    u64                     cfg1_mod_base;
    void __iomem            *va_cfg1_base;
    u32                     cfg1_size;
-   u64                     io_base;
+   resource_size_t                 io_base;
    u64                     io_mod_base;
    phys_addr_t             io_bus_addr;
    u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
    u64                     mem_mod_base;
    phys_addr_t             mem_bus_addr;
    u32                     mem_size;
-   struct resource         cfg;
-   struct resource         io;
-   struct resource         mem;
-   struct resource         busn;
+   struct resource         *cfg;
+   struct resource         *io;
+   struct resource         *mem;
+   struct resource         *busn;
    int                     irq;
    u32                     lanes;
    struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 12 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
            return ret;
    }
 
-   pp->root_bus_nr = -1;
+   pp->root_bus_nr = 0;
    pp->ops = &spear13xx_pcie_host_ops;
 
    ret = dw_pcie_host_init(pp);
 
--------------------------------------------------
--------------------------------------------------
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Wangzhou (B)
Sent: Thursday, June 11, 2015 6:44 AM
To: Gabriele Paoloni
Cc: Lorenzo Pieralisi; James Morse; Bjorn Helgaas; Jingoo Han;

Pratyush

Quoted 1 line
Quoted 1 line

Anand; Arnd Bergmann; fabrice.gasnier at st.com; Liviu Dudau;

linux-

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support

Quoted 3 lines · Gabriele Paoloni

Hi Zhou Wang and all

I have worked on a patch that unify ARM and ARM64. As you can

see I

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

have removed the parser and now I use "of_pci_get_host_bridge_resources" in order to retrieve the

resources

Quoted 2 lines
Quoted 2 lines

associated to each pci host bridge window.

Quoted 1 line

The resources now are not copied to the designware pcie_port

pp,

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

instead they are passed by pointer.

Quoted 2 lines

This patch is intended to replace entirely "[PATCH v2 2/4]";

so I

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

have also included all the changes about the other drivers

Quoted 7 lines

Please find the patch inline below.

Let me know if you think it is ok.

Regards

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Gab

------------------------------------
------------------------------------

This patch is a rework of
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" from Zhou

Wang.

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

The intention is to complete the unification between ARM and ARM64 now that the dependency on arch/arm/kernel/bios32.c is

gone.

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 5 lines

I have also included the rework asked by James Morse:
io_base declared as resource_size_t

It compiles fine on ARCH arm and arm64.

Hi Gabriele,

I manually apply this patch on my series, as there are some

format

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

errors
about this patch. And I think this patch is a experimental one,

it

Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines

could not
be compiled successfully.

Quoted 16 lines

It needs to be tested.

[...]

drivers/pci/host/pcie-designware.c +2 -3
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
  struct device_node *np = pp->dev->of_node;
  struct platform_device *pdev = to_platform_device(pp->dev);
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
  struct resource *cfg_res;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 6 lines

+ LIST_HEAD(res);
u32 val, na, ns;
const __be32 *addrp;
int i, index, ret;
+ int rlen;
+ struct pci_host_bridge_window *win;

This struct is not in latest kernel, I think you should use

struct

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

resource_entry.

Thanks,
Zhou

Quoted 1 line

+ const __be32 *parser_range_end = of_get_property(np,

"ranges",

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

&rlen);

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 7 lines
drivers/pci/host/pcie-designware.c +5 -0
+
+ if (parser_range_end == NULL)
+                 return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+
 
  /* Find the address cell size and the number of cells in

order to

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

get

Review int dw_pcie_host_init(struct pcie_port

Quoted 2 lines

* the untranslated address.

(quoted diff) +0 -0
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port

*pp)

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 8 lines
drivers/pci/host/pcie-designware.c +1 -4
          dev_err(pp->dev, "missing *config* reg space\n");
  }
 
- if (of_pci_range_parser_init(&parser, np)) {
-         dev_err(pp->dev, "missing ranges property\n");
-         return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,

&pp-

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 7 lines
drivers/pci/host/pcie-designware.c +2 -2
 io_base);
+ if (ret)
+         return ret;
 
  /* Get the I/O and memory ranges from DT */
- for_each_of_pci_range(&parser, &range) {
-         unsigned long restype = range.flags &

IORESOURCE_TYPE_BITS;

Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +0 -3
-
-         if (restype == IORESOURCE_IO) {
-                 of_pci_range_to_resource(&range, np, &pp-

io);

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/pci/host/pcie-designware.c +0 -4
-                 pp->io.name = "I/O";
-                 pp->io.start = max_t(resource_size_t,
-                                      PCIBIOS_MIN_IO,
-                                      range.pci_addr +

global_io_offset);

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +0 -3
-                 pp->io.end = min_t(resource_size_t,
-                                    IO_SPACE_LIMIT,
-                                    range.pci_addr +

range.size

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -7
-                                    + global_io_offset - 1);
-                 pp->io_size = resource_size(&pp->io);
-                 pp->io_bus_addr = range.pci_addr;
-                 pp->io_base = range.cpu_addr;
-
-                 /* Find the untranslated IO space address */
-                 pp->io_mod_base =

of_read_number(parser.range -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 404

Quoted 1 line
(quoted diff) +0 -1
-                                                  parser.np +

na, ns);

Quoted 9 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +0 -3
-         }
-         if (restype == IORESOURCE_MEM) {
-                 of_pci_range_to_resource(&range, np, &pp-

mem);

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-                 pp->mem.name = "MEM";
-                 pp->mem_size = resource_size(&pp->mem);
-                 pp->mem_bus_addr = range.pci_addr;
-
-                 /* Find the untranslated MEM space address

*/

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 413

Quoted 1 line
(quoted diff) +0 -1
-                 pp->mem_mod_base =

of_read_number(parser.range -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 414

Quoted 1 line
(quoted diff) +0 -1
-                                                   parser.np

+ na, ns);

Quoted 9 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +0 -3
-         }
-         if (restype == 0) {
-                 of_pci_range_to_resource(&range, np, &pp-

cfg);

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +0 -4
-                 pp->cfg0_size = resource_size(&pp->cfg)/2;
-                 pp->cfg1_size = resource_size(&pp->cfg)/2;
-                 pp->cfg0_base = pp->cfg.start;
-                 pp->cfg1_base = pp->cfg.start + pp-

cfg0_size;

Quoted 9 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 7 lines
drivers/pci/host/pcie-designware.c +7 -0
+ list_for_each_entry(win, &res, list) {
+         switch (resource_type(win->res)) {
+         case IORESOURCE_IO:
+                 pp->io = win->res;
+                 pp->io->name = "I/O";
+                 pp->io_size = resource_size(pp->io);
+                 pp->io_bus_addr = pp->io->start - win-

offset;

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
(quoted diff) +1 -0
+                 /* magic 5 below comes from magic na and ns

in

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 392

Quoted 1 line
(quoted diff) +1 -0
+                  * of_pci_range_parser_init()

*/

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 393

Quoted 1 line
(quoted diff) +1 -0
+                 pp->io_mod_base =

of_read_number(parser_range_end -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 394

Quoted 1 line
(quoted diff) +1 -0
+                                 of_n_addr_cells(np) - 5 + na,

ns);

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +3 -0
+                 ret = pci_remap_iospace(pp->io, pp->io_base);
+                 if (ret) {
+                         dev_warn(pp->dev, "error %d: failed

to map

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

resource %pR\n",

Quoted 9 lines
drivers/pci/host/pcie-designware.c +9 -0
+                         ret, pp->io);
+                 continue;
+                 }
+                 break;
+         case IORESOURCE_MEM:
+                 pp->mem = win->res;
+                 pp->mem->name = "MEM";
+                 pp->mem_size = resource_size(pp->mem);
+                 pp->mem_bus_addr = pp->mem->start - win-
Quoted 2 lines

offset;

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
(quoted diff) +1 -0
+                 pp->mem_mod_base =

of_read_number(parser_range_end -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 408

Quoted 1 line
(quoted diff) +1 -0
+                                 of_n_addr_cells(np) - 5 + na,

ns);

Quoted 10 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 7 lines
drivers/pci/host/pcie-designware.c +7 -0
+                 break;
+         case 0:
+                 pp->cfg = win->res;
+                 pp->cfg0_size = resource_size(pp->cfg)/2;
+                 pp->cfg1_size = resource_size(pp->cfg)/2;
+                 pp->cfg0_base = pp->cfg->start;
+                 pp->cfg1_base = pp->cfg->start + pp-

cfg0_size;

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
(quoted diff) +0 -0
                  /* Find the untranslated configuration space

address

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

*/

Quoted 1 line
(quoted diff) +0 -1
-                 pp->cfg0_mod_base =

of_read_number(parser.range -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 424

Quoted 1 line
(quoted diff) +0 -1
-                                                    parser.np

+ na, ns);

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +1 -2
-                 pp->cfg1_mod_base = pp->cfg0_mod_base +
-                                     pp->cfg0_size;
+                 pp->cfg0_mod_base =

of_read_number(parser_range_end -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 418

Quoted 1 line
(quoted diff) +1 -0
+                                 of_n_addr_cells(np) - 5 + na,

ns);

Quoted 18 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct pcie_port · line 419

Quoted 1 line
(quoted diff) +1 -0
+                 pp->cfg1_mod_base = pp->cfg0_mod_base + pp-

cfg0_size;

Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
drivers/pci/host/pcie-designware.c +6 -7
+                 break;
+         case IORESOURCE_BUS:
+                 pp->busn = win->res;
+                 break;
+         default:
+                 continue;
          }
  }
 
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
-         pp->busn.name = np->name;
-         pp->busn.start = 0;
-         pp->busn.end = 0xff;
-         pp->busn.flags = IORESOURCE_BUS;
-         dev_dbg(pp->dev, "failed to parse bus-range

property: %d,

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines

using default %pR\n",

Quoted 14 lines
drivers/pci/host/pcie-designware.c +2 -5
-                 ret, &pp->busn);
- }
-
  if (!pp->dbi_base) {
-         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-                                 resource_size(&pp->cfg));
+         pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+                                 resource_size(pp->cfg));
          if (!pp->dbi_base) {
                  dev_err(pp->dev, "error with ioremap\n");
                  return -ENOMEM;
          }
  }
 
Quoted 29 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 5 lines
drivers/pci/host/pcie-designware.c +1 -1
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
 
  if (!pp->va_cfg0_base) {
          pp->va_cfg0_base = devm_ioremap(pp->dev, pp-

cfg0_base, @@

Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
Quoted 23 lines

-493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 10 lines
  if (pp->ops->host_init)
          pp->ops->host_init(pp);

- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)

drivers/pci/host/pcie-designware.c +2 -1
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
  /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI);

Quoted 1 line

+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,

PCI_CLASS_BRIDGE_PCI)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +2 -1
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
 
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

&val);

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val);

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

val)

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 4 lines
drivers/pci/host/pcie-designware.c +4 -0
+                 != PCIBIOS_SUCCESSFUL)
+         return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+                       pp, &res);
+ if (!bus)
+         return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 4 lines
drivers/pci/host/pcie-designware.c +2 -0
+domain); #else
+ bus->msi = &dw_pcie_msi_chip;
 #endif
 

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 521

Quoted 10 lines
drivers/pci/host/pcie-designware.c +6 -3
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+         pp->ops->scan_bus(pp);
 
- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);

#endif

Quoted 4 lines

+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines

Review static int dw_pcie_valid_config(struct

Quoted 3 lines

return 0;
}

(quoted diff) +0 -0
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct

pcie_port

Quoted 1 line
Quoted 1 line

*pp, static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn,

int

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

where,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +1 -1
                  int size, u32 *val)
 {
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
  int ret;
 
  if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)

{ @@ -

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,

u32

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

devfn, int where, static int dw_pcie_wr_conf(struct pci_bus

*bus,

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

u32

Quoted 8 lines
Quoted 8 lines

devfn,

Quoted 7 lines
drivers/pci/host/pcie-designware.c +0 -0
                  int where, int size, u32 val)

{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;

if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) @@

-

Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 27 lines
Quoted 18 lines
Quoted 18 lines

701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {

Quoted 17 lines

.write = dw_pcie_wr_conf,
};

drivers/pci/host/pcie-designware.c +0 -14
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) -{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
-         sys->io_offset = global_io_offset - pp->io_bus_addr;
-         pci_ioremap_io(global_io_offset, pp->io_base);
-         global_io_offset += SZ_64K;
-         pci_add_resource_offset(&sys->resources, &pp->io,
-                                 sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines

- pci_add_resource_offset(&sys->resources, &pp->mem, sys- mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);

drivers/pci/host/pcie-designware.c +0 -5
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct

pci_sys_data

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

*sys) -{

Quoted 6 lines

- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);

drivers/pci/host/pcie-designware.c +0 -4
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
-                           &dw_pcie_ops, sys, &sys-

resources);

Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

- if (!bus)

drivers/pci/host/pcie-designware.c +0 -3
-         return NULL;
-
- pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
- if (bus && pp->ops->scan_bus)
-         pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,

u8

Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
Quoted 69 lines

pin) -{

Review

Quoted 19 lines

- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;

drivers/pci/host/pcie-designware.c +0 -14
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
-         irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup          = dw_pcie_setup,
- .scan           = dw_pcie_scan_bus,
- .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
  u32 val;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-designware.h

Review

Quoted 28 lines

index d0bbd27..ab78710 100644

drivers/pci/host/pcie-designware.h +5 -5
@@ -34,7 +34,7 @@ struct pcie_port {
  u64                     cfg1_mod_base;
  void __iomem            *va_cfg1_base;
  u32                     cfg1_size;
- u64                     io_base;
+ resource_size_t                 io_base;
  u64                     io_mod_base;
  phys_addr_t             io_bus_addr;
  u32                     io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
  u64                     mem_mod_base;
  phys_addr_t             mem_bus_addr;
  u32                     mem_size;
- struct resource         cfg;
- struct resource         io;
- struct resource         mem;
- struct resource         busn;
+ struct resource         *cfg;
+ struct resource         *io;
+ struct resource         *mem;
+ struct resource         *busn;
  int                     irq;
  u32                     lanes;
  struct pcie_host_ops    *ops;
(quoted diff) +0 -0

b/drivers/pci/host/pcie-spear13xx.c

drivers/pci/host/pcie-spear13xx.c static int spear13xx_add_pcie_port(struct

Quoted 4 lines

index 020d788..e78ddf8 100644

drivers/pci/host/pcie-spear13xx.c +0 -0
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct

pcie_port *pp,

Quoted 14 lines
drivers/pci/host/pcie-spear13xx.c +1 -3
          return ret;
  }
 
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
  pp->ops = &spear13xx_pcie_host_ops;
 
  ret = dw_pcie_host_init(pp);
------------------------------------
------------------------------------
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

-----Original Message-----
From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
Sent: Tuesday, June 09, 2015 12:15 PM
To: Wangzhou (B)
Cc: James Morse; Bjorn Helgaas; Jingoo Han; Pratyush Anand;

Arnd

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Bergmann; fabrice.gasnier at st.com; Liviu Dudau; linux- pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; Gabriele Paoloni; Yuanzhichang;

Zhudacai;

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64

support

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines · Zhou Wang

[...]

Quoted 5 lines
Quoted 5 lines

drivers/pci/host/pcie-designware.c static const struct irq_domain_ops msi_domain_ops = {

Quoted 5 lines
drivers/pci/host/pcie-designware.c +1 -1
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
      struct device_node *np = pp->dev->of_node;
      struct platform_device *pdev =

to_platform_device(pp->dev);

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct

Quoted 9 lines
      struct of_pci_range range;
      struct of_pci_range_parser parser;
drivers/pci/host/pcie-designware.c +2 -0
+     struct pci_bus *bus;
      struct resource *cfg_res;
+     LIST_HEAD(res);
      u32 val, na, ns;
      const __be32 *addrp;
      int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct

pcie_port

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

*pp)

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
(quoted diff) +0 -0
      val |= PORT_LOGIC_SPEED_CHANGE;
      dw_pcie_wr_own_conf(pp,

PCIE_LINK_WIDTH_SPEED_CONTROL, 4,

Quoted 17 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines

val);

Quoted 12 lines
Quoted 12 lines

Review int dw_pcie_host_init(struct · line 507

Quoted 12 lines
(quoted diff) +8 -3
-#ifdef CONFIG_PCI_MSI
-     dw_pcie_msi_chip.dev = pp->dev;
-     dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+     /*
+      * FIXME: we should really be able to use
+      * of_pci_get_host_bridge_resources on arm32 as well,
+      * but the conversion needs some more testing
+      */
+     if (global_io_offset < SZ_1M && pp->io_size > 0) {
+             pci_ioremap_io(global_io_offset, pp-

io_base);

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
(quoted diff) +3 -0
+             global_io_offset += SZ_64K;
+             pci_add_resource_offset(&res, &pp->io,
+                                     global_io_offset -

pp->io_bus_addr);

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Review int dw_pcie_host_init(struct · line 513

Quoted 3 lines
(quoted diff) +3 -0
+     }
+     pci_add_resource_offset(&res, &pp->mem,
+                             pp->mem.start - pp-

mem_bus_addr);

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Review int dw_pcie_host_init(struct · line 514

Quoted 1 line
(quoted diff) +1 -0
+     pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of

'the

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

conversion needs some more testing', I removed it leaving

just

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

the

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

below arm64 code.

Quoted 2 lines
Quoted 2 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I

went

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

as

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if

we

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

use

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line
Quoted 1 line

PCIe device with a I/O Bar, it may not work well without

above

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

code.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

But so far, I have not met a PCIe device which must work

with a

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

I/O

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Bar.

There are two problems here:

1) the io_base address you get from

of_pci_get_host_bridge_resources

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

must be mapped using pci_remap_iospace. You are not doing

this,

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

so

Quoted 1 line
Quoted 1 line

even if you had a PCIe card with I/O bar it would not work

on

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

arm64

Quoted 1 line
Quoted 1 line

as the code stands. Remember that I/O space on arm/arm64

works

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

as

Quoted 2 lines
Quoted 2 lines

a

Quoted 1 line
Quoted 1 line

memory access with offset from PCI_IOBASE and that's the

value

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 9 lines
Quoted 9 lines

you

Quoted 8 lines
Quoted 8 lines

get
in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

2) (1) above would sort out I/O space access for both arm and

arm64

Quoted 3 lines
Quoted 3 lines

so,

Quoted 2 lines
Quoted 2 lines

as James said, the #ifdef is useless.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

I hope this makes things clearer.

Thanks,
Lorenzo

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
(quoted diff) +2 -0
+#else
+     ret = of_pci_get_host_bridge_resources(np, 0, 0xff,

&res,

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Review int dw_pcie_host_init(struct · line 517

Quoted 1 line
(quoted diff) +1 -0
+&pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be

a

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

resource_size_t*, but &io_base is u64*. This generates a

warning

Quoted 37 lines
Quoted 37 lines
Quoted 37 lines
Quoted 37 lines
Quoted 37 lines
Quoted 37 lines

on

Quoted 36 lines
Quoted 36 lines
Quoted 11 lines
Quoted 8 lines

arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

OK, will modify this in next version.

Quoted 7 lines

Best Regards and thanks again for your test, Zhou

Quoted 5 lines

Review int dw_pcie_host_init(struct · line 522

Quoted 5 lines
(quoted diff) +5 -0
+     if (ret)
+             return ret;
+#endif
+
+     bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,

&dw_pcie_ops,

Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 6 lines
drivers/pci/host/pcie-designware.c +6 -0
+                           pp, &res);
+     if (!bus)
+             return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+     bus->msi = container_of(&pp->irq_domain, struct

msi_controller,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5 -2
+domain); #else
+     bus->msi = &dw_pcie_msi_chip;
 #endif
 
-     dw_pci.nr_controllers = 1;
-     dw_pci.private_data = (void **)&pp;
+     pci_scan_child_bus(bus);
+     if (pp->ops->scan_bus)
+             pp->ops->scan_bus(pp);
 
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp)

Quoted 3 lines
drivers/pci/host/pcie-designware.c +2 -1
-     pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+     /* support old dtbs that incorrectly describe IRQs

*/

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 1 line
Quoted 1 line

Review int dw_pcie_host_init(struct · line 539

Quoted 1 line
(quoted diff) +1 -0
+     pci_fixup_irqs(pci_common_swizzle,

of_irq_parse_and_map_pci);

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/pci/host/pcie-designware.c +4 -0
+#endif
+
+     pci_assign_unassigned_bus_resources(bus);
+     pci_bus_add_devices(bus);
 
      return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct

pcie_port *pp, static int dw_pcie_rd_conf(struct pci_bus

*bus,

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

u32 devfn, int where,

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
                      int size, u32 *val)

{

drivers/pci/host/pcie-designware.c +1 -1
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn))

== 0)

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

{ @@

Quoted 1 line
Quoted 1 line
Quoted 1 line

-677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus

*bus,

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

u32 devfn, int where, static int dw_pcie_wr_conf(struct

pci_bus

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

*bus, u32 devfn,

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

int where, int size, u32 val)
{

drivers/pci/host/pcie-designware.c +1 -1
-     struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+     struct pcie_port *pp = bus->sysdata;
      int ret;
 
      if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn))

== 0) @@

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

-701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
.write = dw_pcie_wr_conf,
};

-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)

-{

Quoted 11 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 6 lines
drivers/pci/host/pcie-designware.c +0 -6
-     struct pcie_port *pp;
-
-     pp = sys_to_pcie(sys);
-
-     if (global_io_offset < SZ_1M && pp->io_size > 0) {
-             sys->io_offset = global_io_offset - pp-

io_bus_addr;

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

- pci_ioremap_io(global_io_offset, pp-

io_base);

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
(quoted diff) +0 -2
-             global_io_offset += SZ_64K;
-             pci_add_resource_offset(&sys->resources,

&pp->io,

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-                                     sys->io_offset);
-     }
-
-     sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-     pci_add_resource_offset(&sys->resources, &pp->mem,

sys-

Quoted 15 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines

mem_offset);

Quoted 5 lines
Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -5
-     pci_add_resource(&sys->resources, &pp->busn);
-
-     return 1;
-}
-
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines

-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) -{

drivers/pci/host/pcie-designware.c +0 -6
-     struct pci_bus *bus;
-     struct pcie_port *pp = sys_to_pcie(sys);
-
-     pp->root_bus_nr = sys->busnr;
-     bus = pci_create_root_bus(pp->dev, sys->busnr,
-                               &dw_pcie_ops, sys, &sys-

resources);

Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/pci/host/pcie-designware.c +0 -4
-     if (!bus)
-             return NULL;
-
-     pci_scan_child_bus(bus);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = {

Quoted 8 lines
drivers/pci/host/pcie-designware.c +0 -8
-
-     if (bus && pp->ops->scan_bus)
-             pp->ops->scan_bus(pp);
-
-     return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8

slot,

Quoted 29 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

u8

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

pin) -{
- struct pcie_port *pp = sys_to_pcie(dev->bus-

sysdata);

Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 12 lines
Quoted 12 lines
drivers/pci/host/pcie-designware.c +0 -12
-     int irq;
-
-     irq = of_irq_parse_and_map_pci(dev, slot, pin);
-     if (!irq)
-             irq = pp->irq;
-
-     return irq;
-}
-
-static struct hw_pci dw_pci = {
-     .setup          = dw_pcie_setup,
-     .scan           = dw_pcie_scan_bus,
Quoted 9 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 718

Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -3
-     .map_irq        = dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)  {
      u32 val;

.

--
To unsubscribe from this list: send the line "unsubscribe

linux-

Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 14 lines
Quoted 13 lines
Quoted 9 lines

pci"

Quoted 1 line
Quoted 1 line
Quoted 1 line

in the body of a message to majordomo at vger.kernel.org More

majordomo

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

info at http://vger.kernel.org/majordomo-info.html

.

.

Quoted 6 lines
Quoted 2 lines

.

--
To unsubscribe from this list: send the line "unsubscribe devicetree"

in

Quoted 3 lines

the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html

author
#17 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

In reply to Lorenzo Pieralisi
Quoted 64 lines · Lorenzo Pieralisi

On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:

[...]

Quoted 39 lines
Quoted 39 lines
Quoted 25 lines
drivers/pci/host/pcie-designware.c +8 -4
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 515

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the below arm64 code.

Quoted 7 lines
Quoted 3 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

I think it depends on which kind of PCIe device you use, if we use a PCIe device with a I/O Bar, it may not work well without above code. But so far, I have not met a PCIe device which must work with a I/O Bar.

There are two problems here:

1) the io_base address you get from of_pci_get_host_bridge_resources must be mapped using pci_remap_iospace. You are not doing this, so even if you had a PCIe card with I/O bar it would not work on arm64 as the code stands. Remember that I/O space on arm/arm64 works as a memory access with offset from PCI_IOBASE and that's the value you get in the I/O resource. See:

drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c

Quoted 8 lines

2) (1) above would sort out I/O space access for both arm and arm64 so, as James said, the #ifdef is useless.

I hope this makes things clearer.

Thanks,
Lorenzo

Hi Lorenzo,

Many thanks for your explanation. I have a better understanding now. So I think we could remove #ifdef and add pci_remap_iospace after of_pci_get_host_bridge_resources.

Regards,
Zhou

Quoted 149 lines
Quoted 141 lines
Quoted 10 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 3 lines
drivers/pci/host/pcie-designware.c +2 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Quoted 4 lines

Thanks,

James

OK, will modify this in next version.

Best Regards and thanks again for your test,
Zhou

Quoted 110 lines
Quoted 110 lines
drivers/pci/host/pcie-designware.c +25 -61
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
Quoted 9 lines

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 736

Quoted 5 lines
drivers/pci/host/pcie-designware.c +0 -2
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;

.

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

.

author
#18 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

In reply to James Morse
Quoted 127 lines · James Morse
Quoted 12 lines · Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

I am not very clear about I/O resource management:

Quoted 6 lines
	if (global_io_offset < SZ_1M && pp->io_size > 0) {
		pci_ioremap_io(global_io_offset, pp->io_base);
		global_io_offset += SZ_64K;
		pci_add_resource_offset(&res, &pp->io,
					global_io_offset - pp->io_bus_addr);
	}
Quoted 5 lines

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

I have tested this on a 'Freescale i.MX6 Quad SABRE Lite Board', which also uses a designware pcie host controller (PCI_IMX6). Booted, removed/rescanned the bus, then scanned for wireless access points using the b43 driver. Please note my change below.

Quoted 87 lines
drivers/pci/host/pcie-designware.c +13 -15
index 2e9f84f..b3f0ac7 100644
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -67,17 +68,10 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
 static unsigned long global_io_offset;
 
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
-
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
 	*val = readl(addr);
@@ -238,7 +232,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -281,7 +275,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -310,7 +304,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -342,13 +336,15 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
+	LIST_HEAD(res);
 	u32 val, na, ns;
 	const __be32 *addrp;
 	int i, index, ret;
@@ -502,15 +498,49 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
-	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+	/*
+	 * FIXME: we should really be able to use
+	 * of_pci_get_host_bridge_resources on arm32 as well,
+	 * but the conversion needs some more testing

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 515

Quoted 10 lines
drivers/pci/host/pcie-designware.c +10 -0
+	 */
+	if (global_io_offset < SZ_1M && pp->io_size > 0) {
+		pci_ioremap_io(global_io_offset, pp->io_base);
+		global_io_offset += SZ_64K;
+		pci_add_resource_offset(&res, &pp->io,
+					global_io_offset - pp->io_bus_addr);
+	}
+	pci_add_resource_offset(&res, &pp->mem,
+				pp->mem.start - pp->mem_bus_addr);
+	pci_add_resource(&res, &pp->busn);

I don't think this #ifdef is necessary. In the spirit of 'the conversion needs some more testing', I removed it leaving just the below arm64 code.

Quoted 4 lines

This worked on my Freescale i.MX6 Quad SABRE Lite Board, I went as far as scanning for wireless access points.

Hi James,

I think you are right. We can remove #ifdef as of_pci_get_host_bridge_resources also manages mem, io and bus resources.

And just as Lorenzo said, if we want PCIe cards with IO bar work well, pci_remap_iospace should be added after of_pci_get_host_bridge_resources to map IO cpu address to PCI_IOBASE.

Thanks again for your test :)
Zhou

Quoted 132 lines

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 517

Quoted 2 lines
drivers/pci/host/pcie-designware.c +2 -0
+#else
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);

of_pci_get_host_bridge_resources expects &pp->io_base to be a resource_size_t*, but &io_base is u64*. This generates a warning on arm with the above change. Changing the the type in drivers/pci/host/pcie-designware.h fixes this.

Thanks,

James

Quoted 105 lines
drivers/pci/host/pcie-designware.c +25 -56
+	if (ret)
+		return ret;
+#endif
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +683,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +707,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +731,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_create_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	pci_scan_child_bus(bus);
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}

drivers/pci/host/pcie-designware.c static struct pci_ops dw_pcie_ops = { · line 736

Quoted 10 lines
drivers/pci/host/pcie-designware.c +0 -7
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;

.

#19 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

In reply to Zhou Wang

Hi Zhou Wang,

Thanks for unifying arm and arm64 code.

Quoted 7 lines · Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

I am not very clear about I/O resource management:

Following discussion may help to understand it, specially in the context of designware.

http://marc.info/?l=linux-pci&m=138621989417562&w=2

Quoted 24 lines
Quoted 6 lines
      if (global_io_offset < SZ_1M && pp->io_size > 0) {
              pci_ioremap_io(global_io_offset, pp->io_base);
              global_io_offset += SZ_64K;
              pci_add_resource_offset(&res, &pp->io,
                                      global_io_offset - pp->io_bus_addr);
      }

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 128 +++++++++++++++----------------------
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 7 files changed, 56 insertions(+), 83 deletions(-)

[...]

drivers/pci/host/pci-layerscape.c static int ls_add_pcie_port(struct ls_pcie *pcie) · line 104

Quoted 10 lines
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
        pp = &pcie->pp;
        pp->dev = pcie->dev;
        pp->dbi_base = pcie->dbi;
-       pp->root_bus_nr = -1;
+       pp->root_bus_nr = 0;

similar change for pcie-spear13xx.c should be needed as well.

Quoted 7 lines
drivers/pci/host/pci-layerscape.c +0 -0
        pp->ops = &ls_pcie_host_ops;
 
        ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +0 -0
index 2e9f84f..b3f0ac7 100644

[...]

Quoted 39 lines
drivers/pci/host/pcie-designware.c +32 -5
-#ifdef CONFIG_PCI_MSI
-       dw_pcie_msi_chip.dev = pp->dev;
-       dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+       /*
+        * FIXME: we should really be able to use
+        * of_pci_get_host_bridge_resources on arm32 as well,
+        * but the conversion needs some more testing
+        */
+       if (global_io_offset < SZ_1M && pp->io_size > 0) {
+               pci_ioremap_io(global_io_offset, pp->io_base);
+               global_io_offset += SZ_64K;
+               pci_add_resource_offset(&res, &pp->io,
+                                       global_io_offset - pp->io_bus_addr);
+       }
+       pci_add_resource_offset(&res, &pp->mem,
+                               pp->mem.start - pp->mem_bus_addr);
+       pci_add_resource(&res, &pp->busn);
+#else
+       ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+       if (ret)
+               return ret;
+#endif
+
+       bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                             pp, &res);
+       if (!bus)
+               return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+       bus->msi = &dw_pcie_msi_chip;
 #endif
 
-       dw_pci.nr_controllers = 1;
-       dw_pci.private_data = (void **)&pp;
+       pci_scan_child_bus(bus);
+       if (pp->ops->scan_bus)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 543

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -1
+               pp->ops->scan_bus(pp);
 
-       pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+       /* support old dtbs that incorrectly describe IRQs */
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+       pci_assign_unassigned_bus_resources(bus);
+       pci_bus_add_devices(bus);

As James and Lorenzo has suggested, of_pci_get_host_bridge_resources should work for ARM as well. I would suggest to move that just after cfg resource parsing and
then to remove following piece of code. for_each_of_pci_range(&parser, &range) {
...
}
ret = of_pci_parse_bus_range(np, &pp->busn);

Then you can have a loop like

         list_for_each_entry(entry, &res, node) {
                 struct resource *res_temp = entry->res;
                 if (resource_type(res_temp) == IORESOURCE_IO) {
                 } else if (resource_type(res_temp) == IORESOURCE_MEM) {
                }
         }

where you can fill, xx_size, xx_bus_addr, xx_mod_base etc. You can also remove global_io_offset variable.

~Pratyush

author
#20 lore raw

PATCH v2 2/4 PCI: designware: Add ARM64 support

Hi Pratyush,

sorry for late.

Quoted 11 lines · Pratyush Anand

Hi Zhou Wang,

Thanks for unifying arm and arm64 code.

Quoted 6 lines · Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci, move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in each PCIe host driver which is based on pcie-designware.

Quoted 6 lines
Quoted 1 line

I am not very clear about I/O resource management:

Following discussion may help to understand it, specially in the context of designware.

http://marc.info/?l=linux-pci&m=138621989417562&w=2

Thanks for sharing above information.

Quoted 29 lines
Quoted 26 lines
Quoted 8 lines

      if (global_io_offset < SZ_1M && pp->io_size > 0) {
              pci_ioremap_io(global_io_offset, pp->io_base);
              global_io_offset += SZ_64K;
              pci_add_resource_offset(&res, &pp->io,
                                      global_io_offset - pp->io_bus_addr);
      }

so just move steps in dw_pcie_setup to dw_pcie_host_init.

I have compiled the driver with multi_v7_defconfig. However, I don't have ARM32 PCIe related board to do test. It will be appreciated if someone could help to test it.

---
 drivers/pci/host/pci-dra7xx.c      |   1 +
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 128 +++++++++++++++----------------------
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 7 files changed, 56 insertions(+), 83 deletions(-)

[...]

Quoted 13 lines

drivers/pci/host/pci-layerscape.c static int ls_add_pcie_port(struct ls_pcie *pcie) · line 104

Quoted 10 lines
drivers/pci/host/pci-layerscape.c +1 -1
index 4a6e62f..5c7a9c4 100644
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
        pp = &pcie->pp;
        pp->dev = pcie->dev;
        pp->dbi_base = pcie->dbi;
-       pp->root_bus_nr = -1;
+       pp->root_bus_nr = 0;

similar change for pcie-spear13xx.c should be needed as well.

Right, will add this in next version.

Quoted 71 lines
Quoted 7 lines
drivers/pci/host/pci-layerscape.c +0 -0
        pp->ops = &ls_pcie_host_ops;
 
        ret = dw_pcie_host_init(pp);
drivers/pci/host/pcie-designware.c +0 -0
index 2e9f84f..b3f0ac7 100644

[...]

Quoted 39 lines
drivers/pci/host/pcie-designware.c +32 -5
-#ifdef CONFIG_PCI_MSI
-       dw_pcie_msi_chip.dev = pp->dev;
-       dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+#ifdef CONFIG_ARM
+       /*
+        * FIXME: we should really be able to use
+        * of_pci_get_host_bridge_resources on arm32 as well,
+        * but the conversion needs some more testing
+        */
+       if (global_io_offset < SZ_1M && pp->io_size > 0) {
+               pci_ioremap_io(global_io_offset, pp->io_base);
+               global_io_offset += SZ_64K;
+               pci_add_resource_offset(&res, &pp->io,
+                                       global_io_offset - pp->io_bus_addr);
+       }
+       pci_add_resource_offset(&res, &pp->mem,
+                               pp->mem.start - pp->mem_bus_addr);
+       pci_add_resource(&res, &pp->busn);
+#else
+       ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+       if (ret)
+               return ret;
+#endif
+
+       bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+                             pp, &res);
+       if (!bus)
+               return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+       bus->msi = &dw_pcie_msi_chip;
 #endif
 
-       dw_pci.nr_controllers = 1;
-       dw_pci.private_data = (void **)&pp;
+       pci_scan_child_bus(bus);
+       if (pp->ops->scan_bus)

drivers/pci/host/pcie-designware.c int dw_pcie_host_init(struct pcie_port *pp) · line 543

Quoted 10 lines
drivers/pci/host/pcie-designware.c +8 -1
+               pp->ops->scan_bus(pp);
 
-       pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+       /* support old dtbs that incorrectly describe IRQs */
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+       pci_assign_unassigned_bus_resources(bus);
+       pci_bus_add_devices(bus);

As James and Lorenzo has suggested, of_pci_get_host_bridge_resources should work for ARM as well. I would suggest to move that just after cfg resource parsing and
then to remove following piece of code. for_each_of_pci_range(&parser, &range) {
...
}
ret = of_pci_parse_bus_range(np, &pp->busn);

Then you can have a loop like

Quoted 8 lines
         list_for_each_entry(entry, &res, node) {
                 struct resource *res_temp = entry->res;
                 if (resource_type(res_temp) == IORESOURCE_IO) {
                 } else if (resource_type(res_temp) == IORESOURCE_MEM) {
                }
         }

where you can fill, xx_size, xx_bus_addr, xx_mod_base etc.

I think it will be better to do like this. And Gabriele already shared a patch about this in this series'discussions, I will try to merge his patch in my next version patchset.

Quoted 1 line

You can also remove global_io_offset variable.

will use pci_remap_iospace in next version patch.

Many thanks for your comments
Zhou

Quoted 9 lines

~Pratyush
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

.

author
#21 lore raw

PATCH v2 3/4 PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05

In reply to Zhou Wang

This patch adds PCIe host support for Hisilicon Soc Hip05.

---
 drivers/pci/host/Kconfig     |   5 +
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 258 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c
drivers/pci/host/Kconfig +5 -0
index 1dfb567..486d822 100644
@@ -125,4 +125,9 @@ config PCIE_IPROC_PLATFORM
 	  Say Y here if you want to use the Broadcom iProc PCIe controller
 	  through the generic platform bus interface
 
+config PCI_HISI
+	depends on OF && ARM64
+	bool "Hisilicon Soc HIP05 PCIe controller"
+	select PCIE_DW
+
 endmenu
drivers/pci/host/Makefile +1 -0
index f733b4e..562142e 100644
@@ -15,3 +15,4 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
 obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
drivers/pci/host/pcie-hisi.c new file +258 -0

258 lines not on this page · raw message

Signature · 1 line
1.9.1
#22 lore raw

PATCH v2 3/4 PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05

drivers/pci/host/pcie-hisi.c

Quoted 5 lines · Zhou Wang
drivers/pci/host/pcie-hisi.c new file +0 -0
new file mode 100644
index 0000000..2a4d72e

New file? Please update MAINTAINERS.
(Also add your new Documentation file in patch 4/4 with that patch)

Thanks,

James

author
#23 lore raw

PATCH v2 3/4 PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05

Quoted 11 lines · James Morse

drivers/pci/host/pcie-hisi.c

Quoted 5 lines · Zhou Wang
drivers/pci/host/pcie-hisi.c new file +0 -0
new file mode 100644
index 0000000..2a4d72e

New file? Please update MAINTAINERS.
(Also add your new Documentation file in patch 4/4 with that patch)

Quoted 3 lines

Thanks,

James

Ok, wil add this patch next version.

Thanks,
ZHou

Quoted 7 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

.

author
#24 lore raw

PATCH v2 4/4 Documentation: DT: Add Hisilicon PCIe host binding

In reply to Zhou Wang

This patch adds related DTS binding document for Hisilicon PCIe host driver.

---
 .../devicetree/bindings/pci/hisilicon-pcie.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
Documentation/devicetree/bindings/pci/hisilicon-pcie.txt new file +46 -0
new file mode 100644
index 0000000..6c9b827
@@ -0,0 +1,46 @@
+Hisilicon PCIe host bridge DT description
+
+Hisilicon PCIe host controller is based on Designware PCI core.
+It shares common functions with PCIe Designware core driver and inherits
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt.
+
+Additional properties are described here:
+
+Required properties:
+- compatible: Should contain "hisilicon,hip05-pcie".
+- reg: Should contain rc_dbi, subctrl, config registers location and length.
+- reg-names: Must include the following entries:
+  "rc_dbi": controller configuration registers;
+  "subctrl": whole PCIe hosts configuration registers;
+  "config": PCIe configuration space registers.
+- msi-parent: Should be its_pcie which is an its receiving MSI interrupts.
+- port-id: Should be 0, 1, 2 or 3.
+
+Optional properties:
+- status: Either "ok" or "disabled".
+- dma-coherent: Present if dma operations are coherent.
+
+Example:
+	pcie@0xb0080000 {
+		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+		reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+		      <0x220 0x00000000 0 0x2000>;
+		reg-names = "rc_dbi", "subctrl", "config";
+		bus-range = <0  15>;
+		msi-parent = <&its_pcie>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		dma-coherent;
+		ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
+		num-lanes = <8>;
+		port-id = <1>;
+		#interrupts-cells = <1>;
+		interrupts-map-mask = <0xf800 0 0 7>;
+		interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
+				  0x0 0 0 2 &mbigen_pcie 2 11
+				  0x0 0 0 3 &mbigen_pcie 3 12
+				  0x0 0 0 4 &mbigen_pcie 4 13>;
+		status = "ok";
+	};
Signature · 1 line
1.9.1