linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-06-03  8:35 Zhou Wang
  2015-06-03  8:35 ` [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
                   ` (3 more replies)
  0 siblings, 4 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu,
	Zhou Wang

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

-- 
1.9.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource
  2015-06-03  8:35 [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
@ 2015-06-03  8:35 ` Zhou Wang
  2015-06-04 13:18   ` James Morse
  2015-06-03  8:35 ` [PATCH v2 2/4] PCI: designware: Add ARM64 support Zhou Wang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu,
	Zhou Wang

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.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>

[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(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index fcbbbb1..47588dc 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -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;
 }
 
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 1ab8635..155d05f 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -22,6 +22,8 @@
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 
+#include "../pci.h" /* HACK to see pci_find_host_bridge */
+
 /*
  * 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);
 }
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 232f925..73abca7 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -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;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 353db8d..39e48fc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -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 */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-03  8:35 [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
  2015-06-03  8:35 ` [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
@ 2015-06-03  8:35 ` Zhou Wang
  2015-06-04 13:19   ` James Morse
  2015-06-14 19:18   ` Pratyush Anand
  2015-06-03  8:35 ` [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
  2015-06-03  8:35 ` [PATCH v2 4/4] Documentation: DT: Add Hisilicon PCIe host binding Zhou Wang
  3 siblings, 2 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu,
	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:
>	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.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
 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(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 2d57e19..5c8b6ab 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -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);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index c139237..4b6db6c 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -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);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index fdb9536..c4a80c5 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -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);
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 75333b0..df91f5e 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -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) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index 4a6e62f..5c7a9c4 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -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);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84f..b3f0ac7 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -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
+	 */
+	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)
+		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;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index 020d788..e78ddf8 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -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);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
  2015-06-03  8:35 [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
  2015-06-03  8:35 ` [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
  2015-06-03  8:35 ` [PATCH v2 2/4] PCI: designware: Add ARM64 support Zhou Wang
@ 2015-06-03  8:35 ` Zhou Wang
  2015-06-04 13:23   ` James Morse
  2015-06-03  8:35 ` [PATCH v2 4/4] Documentation: DT: Add Hisilicon PCIe host binding Zhou Wang
  3 siblings, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu,
	Zhou Wang

This patch adds PCIe host support for Hisilicon Soc Hip05.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 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

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 1dfb567..486d822 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -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
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index f733b4e..562142e 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -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
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 0000000..2a4d72e
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,258 @@
+/*
+ * PCIe host controller driver for Hisilicon Hip05 SoCs
+ *
+ * Copyright (C) 2015 Hisilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ *         Dacai Zhu <zhudacai@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_MODE_REG                           0x2800
+#define PCIE_SUBCTRL_SYS_STATE4_REG                     0x6818
+#define PCIE_SLV_DBI_MODE                               0x0
+#define PCIE_SLV_SYSCTRL_MODE                           0x1
+#define PCIE_SLV_CONTENT_MODE                           0x2
+#define PCIE_SLV_MSI_ASID                               0x10
+#define PCIE_LTSSM_LINKUP_STATE                         0x11
+#define PCIE_LTSSM_STATE_MASK                           0x3F
+#define PCIE_MSI_ASID_ENABLE                            (0x1 << 12)
+#define PCIE_MSI_ASID_VALUE                             (0x1 << 16)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1 << 12)
+#define PCIE_MSI_TRANS_REG                              0x1c8
+#define PCIE_MSI_LOW_ADDRESS                            0x1b4
+#define PCIE_MSI_HIGH_ADDRESS                           0x1c4
+#define PCIE_MSI_ADDRESS_VAL                            0xb7010040
+
+#define to_hisi_pcie(x)	container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+	void __iomem *subctrl_base;
+	void __iomem *reg_base;
+	struct msi_controller *msi;
+	u32 port_id;
+	struct pcie_port pp;
+};
+
+static inline void hisi_pcie_subctrl_writel(struct hisi_pcie *pcie,
+					    u32 val, u32 reg)
+{
+	writel(val, pcie->subctrl_base + reg);
+}
+
+static inline u32 hisi_pcie_subctrl_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->subctrl_base + reg);
+}
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+					u32 val, u32 reg)
+{
+	writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->reg_base + reg);
+}
+
+/*
+ * Change mode to indicate the same reg_base to base of PCIe host configure
+ * registers, base of RC configure space or base of vmid/asid context table
+ */
+static void hisi_pcie_change_apb_mode(struct hisi_pcie *pcie, u32 mode)
+{
+	u32 val;
+	u32 bit_mask;
+	u32 bit_shift;
+	u32 port_id = pcie->port_id;
+	u32 reg = PCIE_SUBCTRL_MODE_REG + 0x100 * port_id;
+
+	if ((port_id == 1) || (port_id == 2)) {
+		bit_mask = 0xc;
+		bit_shift = 0x2;
+	} else {
+		bit_mask = 0x6;
+		bit_shift = 0x1;
+	}
+
+	val = hisi_pcie_subctrl_readl(pcie, reg);
+	val = (val & (~bit_mask)) | (mode << bit_shift);
+	hisi_pcie_subctrl_writel(pcie, val, reg);
+}
+
+/* Configure vmid/asid table in PCIe host */
+static void hisi_pcie_config_context(struct hisi_pcie *pcie)
+{
+	int i;
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_CONTENT_MODE);
+
+	/*
+	 * init vmid and asid tables for all PCIes device as 0
+	 * vmid table: 0 ~ 0x3ff, asid table: 0x400 ~ 0x7ff
+	 */
+	for (i = 0; i < 0x800; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ADDRESS_VAL, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ASID_ENABLE | PCIE_MSI_ASID_VALUE,
+			     PCIE_SLV_MSI_ASID);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, PCIE_MSI_TRANS_REG);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+	u32 val;
+
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	val = hisi_pcie_subctrl_readl(hisi_pcie, PCIE_SUBCTRL_SYS_STATE4_REG +
+				      0x100 * hisi_pcie->port_id);
+
+	return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static
+int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+{
+	struct device_node *msi_node;
+	struct msi_controller *msi;
+	struct device_node *np = pp->dev->of_node;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	msi_node = of_parse_phandle(np, "msi-parent", 0);
+	if (!msi_node) {
+		pr_err("failed to find msi-parent\n");
+		return -ENODEV;
+	}
+
+	msi = of_pci_find_msi_chip_by_node(msi_node);
+	hisi_pcie->msi = msi;
+
+	pp->irq_domain = msi->domain;
+
+	return 0;
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+	.link_up = hisi_pcie_link_up,
+	.msi_host_init = hisi_pcie_msi_host_init,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+				     struct platform_device *pdev)
+{
+	int ret;
+	u32 port_id;
+	struct resource busn;
+
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+		dev_err(&pdev->dev, "failed to read port-id\n");
+		return -EINVAL;
+	}
+	if (port_id > 3) {
+		dev_err(&pdev->dev, "Invalid port-id\n");
+		return -EINVAL;
+	}
+
+	hisi_pcie->port_id = port_id;
+
+	if (of_pci_parse_bus_range(pdev->dev.of_node, &busn)) {
+		dev_err(&pdev->dev, "failed to parse bus-ranges\n");
+		return -EINVAL;
+	}
+
+	pp->root_bus_nr = busn.start;
+	pp->ops = &hisi_pcie_host_ops;
+
+	hisi_pcie_config_context(hisi_pcie);
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+	struct hisi_pcie *hisi_pcie;
+	struct pcie_port *pp;
+	struct resource *reg;
+	struct resource *subctrl;
+	int ret;
+
+	hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+	if (!hisi_pcie)
+		return -ENOMEM;
+
+	pp = &hisi_pcie->pp;
+	pp->dev = &pdev->dev;
+
+	subctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subctrl");
+	hisi_pcie->subctrl_base = devm_ioremap_nocache(&pdev->dev,
+					subctrl->start, resource_size(subctrl));
+	if (IS_ERR(hisi_pcie->subctrl_base)) {
+		dev_err(pp->dev, "cannot get subctrl base\n");
+		return PTR_ERR(hisi_pcie->subctrl_base);
+	}
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+	hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+	if (IS_ERR(hisi_pcie->reg_base)) {
+		dev_err(pp->dev, "cannot get reg base\n");
+		return PTR_ERR(hisi_pcie->reg_base);
+	}
+
+	hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+	ret = hisi_add_pcie_port(pp, pdev);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, hisi_pcie);
+
+	return ret;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+	{.compatible = "hisilicon,hip05-pcie",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+	.probe  = hisi_pcie_probe,
+	.driver = {
+		   .name = "hisi-pcie",
+		   .owner = THIS_MODULE,
+		   .of_match_table = hisi_pcie_of_match,
+	},
+};
+
+module_platform_driver(hisi_pcie_driver);
+
+MODULE_AUTHOR("Zhou Wang <wangzhou1@huawei.com>");
+MODULE_AUTHOR("Dacai Zhu <zhudacai@huawei.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 4/4] Documentation: DT: Add Hisilicon PCIe host binding
  2015-06-03  8:35 [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
                   ` (2 preceding siblings ...)
  2015-06-03  8:35 ` [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
@ 2015-06-03  8:35 ` Zhou Wang
  3 siblings, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-03  8:35 UTC (permalink / raw)
  To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu,
	Zhou Wang

This patch adds related DTS binding document for Hisilicon PCIe host driver.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 .../devicetree/bindings/pci/hisilicon-pcie.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
new file mode 100644
index 0000000..6c9b827
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -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";
+	};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource
  2015-06-03  8:35 ` [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
@ 2015-06-04 13:18   ` James Morse
  2015-06-05  3:53     ` Zhou Wang
  0 siblings, 1 reply; 25+ messages in thread
From: James Morse @ 2015-06-04 13:18 UTC (permalink / raw)
  To: Zhou Wang, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu

On 03/06/15 09:35, Zhou Wang wrote:
> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
> index fcbbbb1..47588dc 100644
> --- a/arch/arm/kernel/bios32.c
> +++ b/arch/arm/kernel/bios32.c
> @@ -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;
>  }

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

> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> index 1ab8635..155d05f 100644
> --- a/drivers/pci/host/pci-mvebu.c
> +++ b/drivers/pci/host/pci-mvebu.c
> @@ -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

>  /*
>   * 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);
>  }


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-03  8:35 ` [PATCH v2 2/4] PCI: designware: Add ARM64 support Zhou Wang
@ 2015-06-04 13:19   ` James Morse
  2015-06-05  8:11     ` Zhou Wang
  2015-06-11  2:44     ` Zhou Wang
  2015-06-14 19:18   ` Pratyush Anand
  1 sibling, 2 replies; 25+ messages in thread
From: James Morse @ 2015-06-04 13:19 UTC (permalink / raw)
  To: Zhou Wang, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu

On 03/06/15 09:35, Zhou Wang wrote:
> 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:
>> 	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.

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.

Tested-by: James Morse <james.morse@arm.com>

> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84f..b3f0ac7 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -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
> +	 */
> +	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.


> +#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

> +	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;


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
  2015-06-03  8:35 ` [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
@ 2015-06-04 13:23   ` James Morse
  2015-06-05  8:13     ` Zhou Wang
  0 siblings, 1 reply; 25+ messages in thread
From: James Morse @ 2015-06-04 13:23 UTC (permalink / raw)
  To: Zhou Wang, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, qiuzhenfa, liguozhu

On 03/06/15 09:35, Zhou Wang wrote:
> diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
> new file mode 100644
> index 0000000..2a4d72e
> --- /dev/null
> +++ b/drivers/pci/host/pcie-hisi.c

New file? Please update MAINTAINERS.
(Also add your new Documentation file in patch 4/4 with that patch)


Thanks,

James

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource
  2015-06-04 13:18   ` James Morse
@ 2015-06-05  3:53     ` Zhou Wang
  0 siblings, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-05  3:53 UTC (permalink / raw)
  To: James Morse
  Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau, linux-pci, linux-arm-kernel,
	devicetree, gabriele.paoloni, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liguozhu

On 2015/6/4 21:18, James Morse wrote:
> On 03/06/15 09:35, Zhou Wang wrote:
>> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
>> index fcbbbb1..47588dc 100644
>> --- a/arch/arm/kernel/bios32.c
>> +++ b/arch/arm/kernel/bios32.c
>> @@ -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;
>>  }
> 
> This leaves both 'sys' and 'dev' in this function as unused variables.
> Please remove them too.
> 

Right, will do in next version.

>> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
>> index 1ab8635..155d05f 100644
>> --- a/drivers/pci/host/pci-mvebu.c
>> +++ b/drivers/pci/host/pci-mvebu.c
>> @@ -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
>

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

>>  /*
>>   * 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);
>>  }
> 
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-04 13:19   ` James Morse
@ 2015-06-05  8:11     ` Zhou Wang
  2015-06-09 11:15       ` Lorenzo Pieralisi
  2015-06-11  2:44     ` Zhou Wang
  1 sibling, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-06-05  8:11 UTC (permalink / raw)
  To: James Morse
  Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau, linux-pci, linux-arm-kernel,
	devicetree, gabriele.paoloni, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liguozhu

On 2015/6/4 21:19, James Morse wrote:
> On 03/06/15 09:35, Zhou Wang wrote:
>> 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:
>>> 	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.
> 
> 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.
> 
> Tested-by: James Morse <james.morse@arm.com>
> 

Hi James,

Many thanks for your help to test :)

>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 2e9f84f..b3f0ac7 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -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
>> +	 */
>> +	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.
> 

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.

>> +#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
> 

OK, will modify this in next version.

Best Regards and thanks again for your test,
Zhou

>> +	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;
> 
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
  2015-06-04 13:23   ` James Morse
@ 2015-06-05  8:13     ` Zhou Wang
  0 siblings, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-05  8:13 UTC (permalink / raw)
  To: James Morse
  Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau, linux-pci, linux-arm-kernel,
	devicetree, gabriele.paoloni, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liguozhu

On 2015/6/4 21:23, James Morse wrote:
> On 03/06/15 09:35, Zhou Wang wrote:
>> diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
>> new file mode 100644
>> index 0000000..2a4d72e
>> --- /dev/null
>> +++ b/drivers/pci/host/pcie-hisi.c
> 
> New file? Please update MAINTAINERS.
> (Also add your new Documentation file in patch 4/4 with that patch)
> 
> 
> Thanks,
> 
> James

Ok, wil add this patch next version.

Thanks,
ZHou

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



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-05  8:11     ` Zhou Wang
@ 2015-06-09 11:15       ` Lorenzo Pieralisi
  2015-06-10 13:35         ` Gabriele Paoloni
  2015-06-11  2:51         ` Zhou Wang
  0 siblings, 2 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2015-06-09 11:15 UTC (permalink / raw)
  To: Zhou Wang
  Cc: James Morse, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, qiuzhenfa, liguozhu

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

[...]

> >> -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
> >> +	 */
> >> +	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.
> > 
> 
> 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

> 
> >> +#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
> > 
> 
> OK, will modify this in next version.
> 
> Best Regards and thanks again for your test,
> Zhou
> 
> >> +	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;
> > 
> > 
> > .
> > 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-09 11:15       ` Lorenzo Pieralisi
@ 2015-06-10 13:35         ` Gabriele Paoloni
  2015-06-11  5:44           ` Zhou Wang
  2015-06-11  2:51         ` Zhou Wang
  1 sibling, 1 reply; 25+ messages in thread
From: Gabriele Paoloni @ 2015-06-10 13:35 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Wangzhou (B)
  Cc: James Morse, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa, Liguozhu (Kenneth)

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.

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>


---
 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(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 2d57e19..5c8b6ab 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -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);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index c139237..4b6db6c 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -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);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index fdb9536..c4a80c5 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -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);
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c index 75333b0..df91f5e 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -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) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index 4a6e62f..5c7a9c4 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -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);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84f..31b29a5 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -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;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..ab78710 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -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;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index 020d788..e78ddf8 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -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);
------------------------------------
------------------------------------




> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@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:
> 
> [...]
> 
> > >> -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
> > >> +	 */
> > >> +	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.
> > >
> >
> > 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
> 
> >
> > >> +#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
> > >
> >
> > OK, will modify this in next version.
> >
> > Best Regards and thanks again for your test, Zhou
> >
> > >> +	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;
> > >
> > >
> > > .
> > >
> >
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> > in the body of a message to majordomo@vger.kernel.org More majordomo
> > info at  http://vger.kernel.org/majordomo-info.html
> >

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-04 13:19   ` James Morse
  2015-06-05  8:11     ` Zhou Wang
@ 2015-06-11  2:44     ` Zhou Wang
  1 sibling, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-11  2:44 UTC (permalink / raw)
  To: James Morse
  Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
	fabrice.gasnier, Liviu Dudau, linux-pci, linux-arm-kernel,
	devicetree, gabriele.paoloni, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liguozhu

On 2015/6/4 21:19, James Morse wrote:
> On 03/06/15 09:35, Zhou Wang wrote:
>> 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:
>>> 	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.
> 
> 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.
> 
> Tested-by: James Morse <james.morse@arm.com>
> 
>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 2e9f84f..b3f0ac7 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -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
>> +	 */
>> +	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.
> 
>

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

>> +#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
> 
>> +	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;
> 
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-09 11:15       ` Lorenzo Pieralisi
  2015-06-10 13:35         ` Gabriele Paoloni
@ 2015-06-11  2:51         ` Zhou Wang
  1 sibling, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-11  2:51 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: James Morse, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, qiuzhenfa, liguozhu

On 2015/6/9 19:15, Lorenzo Pieralisi wrote:
> On Fri, Jun 05, 2015 at 09:11:30AM +0100, Zhou Wang wrote:
> 
> [...]
> 
>>>> -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
>>>> +	 */
>>>> +	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.
>>>
>>
>> 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
>

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

>>
>>>> +#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
>>>
>>
>> OK, will modify this in next version.
>>
>> Best Regards and thanks again for your test,
>> Zhou
>>
>>>> +	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;
>>>
>>>
>>> .
>>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-10 13:35         ` Gabriele Paoloni
@ 2015-06-11  5:44           ` Zhou Wang
  2015-06-11 14:32             ` Gabriele Paoloni
  0 siblings, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-06-11  5:44 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, Liguozhu (Kenneth)

On 2015/6/10 21:35, Gabriele Paoloni wrote:
> 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.

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.

> 
> It needs to be tested.
> 
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> 
> [...]
>
> -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;

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

Thanks,
Zhou

> +	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;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..ab78710 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -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;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index 020d788..e78ddf8 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -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);
> ------------------------------------
> ------------------------------------
> 
> 
> 
> 
>> -----Original Message-----
>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>> devicetree@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:
>>
>> [...]
>>
>>>>> -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
>>>>> +	 */
>>>>> +	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.
>>>>
>>>
>>> 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
>>
>>>
>>>>> +#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
>>>>
>>>
>>> OK, will modify this in next version.
>>>
>>> Best Regards and thanks again for your test, Zhou
>>>
>>>>> +	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;
>>>>
>>>>
>>>> .
>>>>
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-pci"
>>> in the body of a message to majordomo@vger.kernel.org More majordomo
>>> info at  http://vger.kernel.org/majordomo-info.html
>>>
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-11  5:44           ` Zhou Wang
@ 2015-06-11 14:32             ` Gabriele Paoloni
  2015-06-16 11:30               ` Zhou Wang
  0 siblings, 1 reply; 25+ messages in thread
From: Gabriele Paoloni @ 2015-06-11 14:32 UTC (permalink / raw)
  To: Wangzhou (B)
  Cc: Lorenzo Pieralisi, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, Liguozhu (Kenneth)

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.

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

---
 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(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 2d57e19..5c8b6ab 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -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);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index c139237..4b6db6c 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -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);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index fdb9536..c4a80c5 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -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);
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 75333b0..df91f5e 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -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) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index 4a6e62f..5c7a9c4 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -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);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84f..844febee 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -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;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..ab78710 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -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;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index 020d788..e78ddf8 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -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);

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

> -----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@st.com; Liviu Dudau; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; Liguozhu (Kenneth)
> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> 
> On 2015/6/10 21:35, Gabriele Paoloni wrote:
> > 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.
> 
> 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.
> 
> >
> > It needs to be tested.
> >
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >
> > [...]
> >
> > -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;
> 
> This struct is not in latest kernel, I think you should use struct
> resource_entry.
> 
> Thanks,
> Zhou
> 
> > +	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;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..ab78710 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -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;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index 020d788..e78ddf8 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -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);
> > ------------------------------------
> > ------------------------------------
> >
> >
> >
> >
> >> -----Original Message-----
> >> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> >> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >> devicetree@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:
> >>
> >> [...]
> >>
> >>>>> -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
> >>>>> +	 */
> >>>>> +	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.
> >>>>
> >>>
> >>> 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
> >>
> >>>
> >>>>> +#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
> >>>>
> >>>
> >>> OK, will modify this in next version.
> >>>
> >>> Best Regards and thanks again for your test, Zhou
> >>>
> >>>>> +	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;
> >>>>
> >>>>
> >>>> .
> >>>>
> >>>
> >>>
> >>> --
> >>> To unsubscribe from this list: send the line "unsubscribe linux-
> pci"
> >>> in the body of a message to majordomo@vger.kernel.org More
> majordomo
> >>> info at  http://vger.kernel.org/majordomo-info.html
> >>>
> >
> > .
> >
> 


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-03  8:35 ` [PATCH v2 2/4] PCI: designware: Add ARM64 support Zhou Wang
  2015-06-04 13:19   ` James Morse
@ 2015-06-14 19:18   ` Pratyush Anand
  2015-06-16 10:14     ` Zhou Wang
  1 sibling, 1 reply; 25+ messages in thread
From: Pratyush Anand @ 2015-06-14 19:18 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, Jingoo Han, Arnd Bergmann, fabrice.gasnier,
	Liviu Dudau, linux-pci, linux-arm-kernel, devicetree,
	Gabriele Paoloni, Zhichang Yuan, zhudacai, Zhang Jukuo,
	qiuzhenfa, Liguozhu

Hi Zhou Wang,

Thanks for unifying arm and arm64 code.

On Wed, Jun 3, 2015 at 2:05 PM, Zhou Wang <wangzhou1@hisilicon.com> wrote:
>
> 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


> >       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.
>
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> ---
>  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(-)
>

[...]

> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index 4a6e62f..5c7a9c4 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -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.

>         pp->ops = &ls_pcie_host_ops;
>
>         ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84f..b3f0ac7 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c

[...]

> -#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)
> +               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

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-14 19:18   ` Pratyush Anand
@ 2015-06-16 10:14     ` Zhou Wang
  0 siblings, 0 replies; 25+ messages in thread
From: Zhou Wang @ 2015-06-16 10:14 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Bjorn Helgaas, Jingoo Han, Arnd Bergmann, fabrice.gasnier,
	Liviu Dudau, linux-pci, linux-arm-kernel, devicetree,
	Gabriele Paoloni, Zhichang Yuan, zhudacai, Zhang Jukuo,
	qiuzhenfa, Liguozhu

Hi Pratyush,

sorry for late.

On 2015/6/15 3:18, Pratyush Anand wrote:
> Hi Zhou Wang,
> 
> Thanks for unifying arm and arm64 code.
> 
> On Wed, Jun 3, 2015 at 2:05 PM, Zhou Wang <wangzhou1@hisilicon.com> wrote:
>>
>> 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

Thanks for sharing above information.

> 
> 
>>>       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.
>>
>> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
>> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>>  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(-)
>>
> 
> [...]
> 
>> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
>> index 4a6e62f..5c7a9c4 100644
>> --- a/drivers/pci/host/pci-layerscape.c
>> +++ b/drivers/pci/host/pci-layerscape.c
>> @@ -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.

>>         pp->ops = &ls_pcie_host_ops;
>>
>>         ret = dw_pcie_host_init(pp);
>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 2e9f84f..b3f0ac7 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
> 
> [...]
> 
>> -#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)
>> +               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.

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.

> You can also remove global_io_offset variable.

will use pci_remap_iospace in next version patch.

Many thanks for your comments
Zhou

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



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-11 14:32             ` Gabriele Paoloni
@ 2015-06-16 11:30               ` Zhou Wang
  2015-06-16 14:14                 ` Gabriele Paoloni
  0 siblings, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-06-16 11:30 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, Liguozhu (Kenneth)

On 2015/6/11 22:32, Gabriele Paoloni wrote:
> 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
> 

Hi Gab,

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

Many thanks for your patch.
Zhou

> -------------------------------------------
> -------------------------------------------
> 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.
> 
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> 
> ---
>  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(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 2d57e19..5c8b6ab 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -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);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index c139237..4b6db6c 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -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);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index fdb9536..c4a80c5 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -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);
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 75333b0..df91f5e 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -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) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index 4a6e62f..5c7a9c4 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -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);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84f..844febee 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -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;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..ab78710 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -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;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index 020d788..e78ddf8 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -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);
> 
> --------------------------------------------------
> --------------------------------------------------
> 
>> -----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@st.com; Liviu Dudau; linux-
>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>> qiuzhenfa; Liguozhu (Kenneth)
>> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
>>
>> On 2015/6/10 21:35, Gabriele Paoloni wrote:
>>> 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.
>>
>> 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.
>>
>>>
>>> It needs to be tested.
>>>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>>
>>> [...]
>>>
>>> -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;
>>
>> This struct is not in latest kernel, I think you should use struct
>> resource_entry.
>>
>> Thanks,
>> Zhou
>>
>>> +	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;
>>> diff --git a/drivers/pci/host/pcie-designware.h
>> b/drivers/pci/host/pcie-designware.h
>>> index d0bbd27..ab78710 100644
>>> --- a/drivers/pci/host/pcie-designware.h
>>> +++ b/drivers/pci/host/pcie-designware.h
>>> @@ -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;
>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
>> b/drivers/pci/host/pcie-spear13xx.c
>>> index 020d788..e78ddf8 100644
>>> --- a/drivers/pci/host/pcie-spear13xx.c
>>> +++ b/drivers/pci/host/pcie-spear13xx.c
>>> @@ -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);
>>> ------------------------------------
>>> ------------------------------------
>>>
>>>
>>>
>>>
>>>> -----Original Message-----
>>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>> devicetree@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:
>>>>
>>>> [...]
>>>>
>>>>>>> -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
>>>>>>> +	 */
>>>>>>> +	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.
>>>>>>
>>>>>
>>>>> 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
>>>>
>>>>>
>>>>>>> +#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
>>>>>>
>>>>>
>>>>> OK, will modify this in next version.
>>>>>
>>>>> Best Regards and thanks again for your test, Zhou
>>>>>
>>>>>>> +	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;
>>>>>>
>>>>>>
>>>>>> .
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe linux-
>> pci"
>>>>> in the body of a message to majordomo@vger.kernel.org More
>> majordomo
>>>>> info at  http://vger.kernel.org/majordomo-info.html
>>>>>
>>>
>>> .
>>>
>>
> 
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-16 11:30               ` Zhou Wang
@ 2015-06-16 14:14                 ` Gabriele Paoloni
  2015-07-13 10:58                   ` Lorenzo Pieralisi
  0 siblings, 1 reply; 25+ messages in thread
From: Gabriele Paoloni @ 2015-06-16 14:14 UTC (permalink / raw)
  To: Wangzhou (B)
  Cc: Lorenzo Pieralisi, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, Liguozhu (Kenneth)


> -----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@st.com; Liviu Dudau; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; Liguozhu (Kenneth)
> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> 
> On 2015/6/11 22:32, Gabriele Paoloni wrote:
> > 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
> >
> 
> Hi Gab,
> 
> I will try to merge your patch into next version, please help to
> review :)
>

Sure I will :)

Thanks

Gab
 
> Many thanks for your patch.
> Zhou
> 
> > -------------------------------------------
> > -------------------------------------------
> > 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.
> >
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >
> > ---
> >  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(-)
> >
> > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> > index 2d57e19..5c8b6ab 100644
> > --- a/drivers/pci/host/pci-dra7xx.c
> > +++ b/drivers/pci/host/pci-dra7xx.c
> > @@ -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);
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index c139237..4b6db6c 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -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);
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> imx6.c
> > index fdb9536..c4a80c5 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -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);
> > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> > index 75333b0..df91f5e 100644
> > --- a/drivers/pci/host/pci-keystone.c
> > +++ b/drivers/pci/host/pci-keystone.c
> > @@ -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) {
> > diff --git a/drivers/pci/host/pci-layerscape.c
> b/drivers/pci/host/pci-layerscape.c
> > index 4a6e62f..5c7a9c4 100644
> > --- a/drivers/pci/host/pci-layerscape.c
> > +++ b/drivers/pci/host/pci-layerscape.c
> > @@ -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);
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index 2e9f84f..844febee 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -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;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..ab78710 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -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;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index 020d788..e78ddf8 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -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);
> >
> > --------------------------------------------------
> > --------------------------------------------------
> >
> >> -----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@st.com; Liviu Dudau; linux-
> >> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >> qiuzhenfa; Liguozhu (Kenneth)
> >> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> >>
> >> On 2015/6/10 21:35, Gabriele Paoloni wrote:
> >>> 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.
> >>
> >> 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.
> >>
> >>>
> >>> It needs to be tested.
> >>>
> >>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >>>
> >>> [...]
> >>>
> >>> -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;
> >>
> >> This struct is not in latest kernel, I think you should use struct
> >> resource_entry.
> >>
> >> Thanks,
> >> Zhou
> >>
> >>> +	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;
> >>> diff --git a/drivers/pci/host/pcie-designware.h
> >> b/drivers/pci/host/pcie-designware.h
> >>> index d0bbd27..ab78710 100644
> >>> --- a/drivers/pci/host/pcie-designware.h
> >>> +++ b/drivers/pci/host/pcie-designware.h
> >>> @@ -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;
> >>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> >> b/drivers/pci/host/pcie-spear13xx.c
> >>> index 020d788..e78ddf8 100644
> >>> --- a/drivers/pci/host/pcie-spear13xx.c
> >>> +++ b/drivers/pci/host/pcie-spear13xx.c
> >>> @@ -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);
> >>> ------------------------------------
> >>> ------------------------------------
> >>>
> >>>
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> >>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >>>> devicetree@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:
> >>>>
> >>>> [...]
> >>>>
> >>>>>>> -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
> >>>>>>> +	 */
> >>>>>>> +	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.
> >>>>>>
> >>>>>
> >>>>> 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
> >>>>
> >>>>>
> >>>>>>> +#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
> >>>>>>
> >>>>>
> >>>>> OK, will modify this in next version.
> >>>>>
> >>>>> Best Regards and thanks again for your test, Zhou
> >>>>>
> >>>>>>> +	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;
> >>>>>>
> >>>>>>
> >>>>>> .
> >>>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> To unsubscribe from this list: send the line "unsubscribe linux-
> >> pci"
> >>>>> in the body of a message to majordomo@vger.kernel.org More
> >> majordomo
> >>>>> info at  http://vger.kernel.org/majordomo-info.html
> >>>>>
> >>>
> >>> .
> >>>
> >>
> >
> >
> > .
> >
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-06-16 14:14                 ` Gabriele Paoloni
@ 2015-07-13 10:58                   ` Lorenzo Pieralisi
  2015-07-13 11:45                     ` Zhou Wang
  0 siblings, 1 reply; 25+ messages in thread
From: Lorenzo Pieralisi @ 2015-07-13 10:58 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Wangzhou (B),
	James Morse, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa, liguozhu

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

[...]

> > > +   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

> > > +   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;
> > > diff --git a/drivers/pci/host/pcie-designware.h
> > b/drivers/pci/host/pcie-designware.h
> > > index d0bbd27..ab78710 100644
> > > --- a/drivers/pci/host/pcie-designware.h
> > > +++ b/drivers/pci/host/pcie-designware.h
> > > @@ -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;
> > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > b/drivers/pci/host/pcie-spear13xx.c
> > > index 020d788..e78ddf8 100644
> > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > @@ -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);
> > >
> > > --------------------------------------------------
> > > --------------------------------------------------
> > >
> > >> -----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@st.com; Liviu Dudau; linux-
> > >> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > >> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > >> qiuzhenfa; Liguozhu (Kenneth)
> > >> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> > >>
> > >> On 2015/6/10 21:35, Gabriele Paoloni wrote:
> > >>> 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.
> > >>
> > >> 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.
> > >>
> > >>>
> > >>> It needs to be tested.
> > >>>
> > >>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > >>>
> > >>> [...]
> > >>>
> > >>> -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;
> > >>
> > >> This struct is not in latest kernel, I think you should use struct
> > >> resource_entry.
> > >>
> > >> Thanks,
> > >> Zhou
> > >>
> > >>> + 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;
> > >>> diff --git a/drivers/pci/host/pcie-designware.h
> > >> b/drivers/pci/host/pcie-designware.h
> > >>> index d0bbd27..ab78710 100644
> > >>> --- a/drivers/pci/host/pcie-designware.h
> > >>> +++ b/drivers/pci/host/pcie-designware.h
> > >>> @@ -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;
> > >>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> > >> b/drivers/pci/host/pcie-spear13xx.c
> > >>> index 020d788..e78ddf8 100644
> > >>> --- a/drivers/pci/host/pcie-spear13xx.c
> > >>> +++ b/drivers/pci/host/pcie-spear13xx.c
> > >>> @@ -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);
> > >>> ------------------------------------
> > >>> ------------------------------------
> > >>>
> > >>>
> > >>>
> > >>>
> > >>>> -----Original Message-----
> > >>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> > >>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > >>>> devicetree@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:
> > >>>>
> > >>>> [...]
> > >>>>
> > >>>>>>> -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
> > >>>>>>> +      */
> > >>>>>>> +     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.
> > >>>>>>
> > >>>>>
> > >>>>> 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
> > >>>>
> > >>>>>
> > >>>>>>> +#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
> > >>>>>>
> > >>>>>
> > >>>>> OK, will modify this in next version.
> > >>>>>
> > >>>>> Best Regards and thanks again for your test, Zhou
> > >>>>>
> > >>>>>>> +     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;
> > >>>>>>
> > >>>>>>
> > >>>>>> .
> > >>>>>>
> > >>>>>
> > >>>>>
> > >>>>> --
> > >>>>> To unsubscribe from this list: send the line "unsubscribe linux-
> > >> pci"
> > >>>>> in the body of a message to majordomo@vger.kernel.org More
> > >> majordomo
> > >>>>> info at  http://vger.kernel.org/majordomo-info.html
> > >>>>>
> > >>>
> > >>> .
> > >>>
> > >>
> > >
> > >
> > > .
> > >
> >
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-07-13 10:58                   ` Lorenzo Pieralisi
@ 2015-07-13 11:45                     ` Zhou Wang
  2015-07-13 14:17                       ` Lorenzo Pieralisi
  0 siblings, 1 reply; 25+ messages in thread
From: Zhou Wang @ 2015-07-13 11:45 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Gabriele Paoloni, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, liguozhu

On 2015/7/13 18:58, Lorenzo Pieralisi wrote:
> On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:
> 
> [...]
> 
>>>> +   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
>

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

>>>> +   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;
>>>> diff --git a/drivers/pci/host/pcie-designware.h
>>> b/drivers/pci/host/pcie-designware.h
>>>> index d0bbd27..ab78710 100644
>>>> --- a/drivers/pci/host/pcie-designware.h
>>>> +++ b/drivers/pci/host/pcie-designware.h
>>>> @@ -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;
>>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
>>> b/drivers/pci/host/pcie-spear13xx.c
>>>> index 020d788..e78ddf8 100644
>>>> --- a/drivers/pci/host/pcie-spear13xx.c
>>>> +++ b/drivers/pci/host/pcie-spear13xx.c
>>>> @@ -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);
>>>>
>>>> --------------------------------------------------
>>>> --------------------------------------------------
>>>>
>>>>> -----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@st.com; Liviu Dudau; linux-
>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>>> qiuzhenfa; Liguozhu (Kenneth)
>>>>> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
>>>>>
>>>>> On 2015/6/10 21:35, Gabriele Paoloni wrote:
>>>>>> 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.
>>>>>
>>>>> 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.
>>>>>
>>>>>>
>>>>>> It needs to be tested.
>>>>>>
>>>>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>> -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;
>>>>>
>>>>> This struct is not in latest kernel, I think you should use struct
>>>>> resource_entry.
>>>>>
>>>>> Thanks,
>>>>> Zhou
>>>>>
>>>>>> + 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;
>>>>>> diff --git a/drivers/pci/host/pcie-designware.h
>>>>> b/drivers/pci/host/pcie-designware.h
>>>>>> index d0bbd27..ab78710 100644
>>>>>> --- a/drivers/pci/host/pcie-designware.h
>>>>>> +++ b/drivers/pci/host/pcie-designware.h
>>>>>> @@ -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;
>>>>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
>>>>> b/drivers/pci/host/pcie-spear13xx.c
>>>>>> index 020d788..e78ddf8 100644
>>>>>> --- a/drivers/pci/host/pcie-spear13xx.c
>>>>>> +++ b/drivers/pci/host/pcie-spear13xx.c
>>>>>> @@ -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);
>>>>>> ------------------------------------
>>>>>> ------------------------------------
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
>>>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>>>>> devicetree@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:
>>>>>>>
>>>>>>> [...]
>>>>>>>
>>>>>>>>>> -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
>>>>>>>>>> +      */
>>>>>>>>>> +     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.
>>>>>>>>>
>>>>>>>>
>>>>>>>> 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
>>>>>>>
>>>>>>>>
>>>>>>>>>> +#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
>>>>>>>>>
>>>>>>>>
>>>>>>>> OK, will modify this in next version.
>>>>>>>>
>>>>>>>> Best Regards and thanks again for your test, Zhou
>>>>>>>>
>>>>>>>>>> +     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;
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> .
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-
>>>>> pci"
>>>>>>>> in the body of a message to majordomo@vger.kernel.org More
>>>>> majordomo
>>>>>>>> info at  http://vger.kernel.org/majordomo-info.html
>>>>>>>>
>>>>>>
>>>>>> .
>>>>>>
>>>>>
>>>>
>>>>
>>>> .
>>>>
>>>
>>
> 
> .
> 



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-07-13 11:45                     ` Zhou Wang
@ 2015-07-13 14:17                       ` Lorenzo Pieralisi
  2015-07-17 10:45                         ` Gabriele Paoloni
  0 siblings, 1 reply; 25+ messages in thread
From: Lorenzo Pieralisi @ 2015-07-13 14:17 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Gabriele Paoloni, James Morse, Bjorn Helgaas, Jingoo Han,
	Pratyush Anand, Arnd Bergmann, fabrice.gasnier, Liviu Dudau,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, liguozhu

On Mon, Jul 13, 2015 at 12:45:52PM +0100, Zhou Wang wrote:
> On 2015/7/13 18:58, Lorenzo Pieralisi wrote:
> > On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:
> >
> > [...]
> >
> >>>> +   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
> >
> 
> 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

> And the latest series is v3 version
> "[PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05"
> 
> Best regards,
> Zhou
> 
> >>>> +   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;
> >>>> diff --git a/drivers/pci/host/pcie-designware.h
> >>> b/drivers/pci/host/pcie-designware.h
> >>>> index d0bbd27..ab78710 100644
> >>>> --- a/drivers/pci/host/pcie-designware.h
> >>>> +++ b/drivers/pci/host/pcie-designware.h
> >>>> @@ -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;
> >>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> >>> b/drivers/pci/host/pcie-spear13xx.c
> >>>> index 020d788..e78ddf8 100644
> >>>> --- a/drivers/pci/host/pcie-spear13xx.c
> >>>> +++ b/drivers/pci/host/pcie-spear13xx.c
> >>>> @@ -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);
> >>>>
> >>>> --------------------------------------------------
> >>>> --------------------------------------------------
> >>>>
> >>>>> -----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@st.com; Liviu Dudau; linux-
> >>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >>>>> qiuzhenfa; Liguozhu (Kenneth)
> >>>>> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> >>>>>
> >>>>> On 2015/6/10 21:35, Gabriele Paoloni wrote:
> >>>>>> 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.
> >>>>>
> >>>>> 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.
> >>>>>
> >>>>>>
> >>>>>> It needs to be tested.
> >>>>>>
> >>>>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >>>>>>
> >>>>>> [...]
> >>>>>>
> >>>>>> -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;
> >>>>>
> >>>>> This struct is not in latest kernel, I think you should use struct
> >>>>> resource_entry.
> >>>>>
> >>>>> Thanks,
> >>>>> Zhou
> >>>>>
> >>>>>> + 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;
> >>>>>> diff --git a/drivers/pci/host/pcie-designware.h
> >>>>> b/drivers/pci/host/pcie-designware.h
> >>>>>> index d0bbd27..ab78710 100644
> >>>>>> --- a/drivers/pci/host/pcie-designware.h
> >>>>>> +++ b/drivers/pci/host/pcie-designware.h
> >>>>>> @@ -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;
> >>>>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> >>>>> b/drivers/pci/host/pcie-spear13xx.c
> >>>>>> index 020d788..e78ddf8 100644
> >>>>>> --- a/drivers/pci/host/pcie-spear13xx.c
> >>>>>> +++ b/drivers/pci/host/pcie-spear13xx.c
> >>>>>> @@ -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);
> >>>>>> ------------------------------------
> >>>>>> ------------------------------------
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>> -----Original Message-----
> >>>>>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> >>>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >>>>>>> devicetree@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:
> >>>>>>>
> >>>>>>> [...]
> >>>>>>>
> >>>>>>>>>> -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
> >>>>>>>>>> +      */
> >>>>>>>>>> +     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.
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> 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
> >>>>>>>
> >>>>>>>>
> >>>>>>>>>> +#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
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> OK, will modify this in next version.
> >>>>>>>>
> >>>>>>>> Best Regards and thanks again for your test, Zhou
> >>>>>>>>
> >>>>>>>>>> +     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;
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> .
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> --
> >>>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-
> >>>>> pci"
> >>>>>>>> in the body of a message to majordomo@vger.kernel.org More
> >>>>> majordomo
> >>>>>>>> info at  http://vger.kernel.org/majordomo-info.html
> >>>>>>>>
> >>>>>>
> >>>>>> .
> >>>>>>
> >>>>>
> >>>>
> >>>>
> >>>> .
> >>>>
> >>>
> >>
> >
> > .
> >
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v2 2/4] PCI: designware: Add ARM64 support
  2015-07-13 14:17                       ` Lorenzo Pieralisi
@ 2015-07-17 10:45                         ` Gabriele Paoloni
  0 siblings, 0 replies; 25+ messages in thread
From: Gabriele Paoloni @ 2015-07-17 10:45 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Wangzhou (B)
  Cc: James Morse, Bjorn Helgaas, Jingoo Han, Pratyush Anand,
	Arnd Bergmann, fabrice.gasnier, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa, Liguozhu (Kenneth)

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; Liguozhu (Kenneth)
> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> 
> On Mon, Jul 13, 2015 at 12:45:52PM +0100, Zhou Wang wrote:
> > On 2015/7/13 18:58, Lorenzo Pieralisi wrote:
> > > On Tue, Jun 16, 2015 at 03:14:21PM +0100, Gabriele Paoloni wrote:
> > >
> > > [...]
> > >
> > >>>> +   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
> > >
> >
> > 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 have submitted a new patch for this:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/357431.html

> 
> 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
> 
> > And the latest series is v3 version
> > "[PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc
> Hip05"
> >
> > Best regards,
> > Zhou
> >
> > >>>> +   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;
> > >>>> diff --git a/drivers/pci/host/pcie-designware.h
> > >>> b/drivers/pci/host/pcie-designware.h
> > >>>> index d0bbd27..ab78710 100644
> > >>>> --- a/drivers/pci/host/pcie-designware.h
> > >>>> +++ b/drivers/pci/host/pcie-designware.h
> > >>>> @@ -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;
> > >>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> > >>> b/drivers/pci/host/pcie-spear13xx.c
> > >>>> index 020d788..e78ddf8 100644
> > >>>> --- a/drivers/pci/host/pcie-spear13xx.c
> > >>>> +++ b/drivers/pci/host/pcie-spear13xx.c
> > >>>> @@ -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);
> > >>>>
> > >>>> --------------------------------------------------
> > >>>> --------------------------------------------------
> > >>>>
> > >>>>> -----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@st.com; Liviu Dudau;
> linux-
> > >>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > >>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > >>>>> qiuzhenfa; Liguozhu (Kenneth)
> > >>>>> Subject: Re: [PATCH v2 2/4] PCI: designware: Add ARM64 support
> > >>>>>
> > >>>>> On 2015/6/10 21:35, Gabriele Paoloni wrote:
> > >>>>>> 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.
> > >>>>>
> > >>>>> 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.
> > >>>>>
> > >>>>>>
> > >>>>>> It needs to be tested.
> > >>>>>>
> > >>>>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > >>>>>>
> > >>>>>> [...]
> > >>>>>>
> > >>>>>> -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;
> > >>>>>
> > >>>>> This struct is not in latest kernel, I think you should use
> struct
> > >>>>> resource_entry.
> > >>>>>
> > >>>>> Thanks,
> > >>>>> Zhou
> > >>>>>
> > >>>>>> + 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;
> > >>>>>> diff --git a/drivers/pci/host/pcie-designware.h
> > >>>>> b/drivers/pci/host/pcie-designware.h
> > >>>>>> index d0bbd27..ab78710 100644
> > >>>>>> --- a/drivers/pci/host/pcie-designware.h
> > >>>>>> +++ b/drivers/pci/host/pcie-designware.h
> > >>>>>> @@ -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;
> > >>>>>> diff --git a/drivers/pci/host/pcie-spear13xx.c
> > >>>>> b/drivers/pci/host/pcie-spear13xx.c
> > >>>>>> index 020d788..e78ddf8 100644
> > >>>>>> --- a/drivers/pci/host/pcie-spear13xx.c
> > >>>>>> +++ b/drivers/pci/host/pcie-spear13xx.c
> > >>>>>> @@ -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);
> > >>>>>> ------------------------------------
> > >>>>>> ------------------------------------
> > >>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>>> -----Original Message-----
> > >>>>>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@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@st.com; Liviu Dudau; linux-
> > >>>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > >>>>>>> devicetree@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:
> > >>>>>>>
> > >>>>>>> [...]
> > >>>>>>>
> > >>>>>>>>>> -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
> > >>>>>>>>>> +      */
> > >>>>>>>>>> +     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.
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>> 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
> > >>>>>>>
> > >>>>>>>>
> > >>>>>>>>>> +#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
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>> OK, will modify this in next version.
> > >>>>>>>>
> > >>>>>>>> Best Regards and thanks again for your test, Zhou
> > >>>>>>>>
> > >>>>>>>>>> +     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;
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>> .
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>> --
> > >>>>>>>> To unsubscribe from this list: send the line "unsubscribe
> linux-
> > >>>>> pci"
> > >>>>>>>> in the body of a message to majordomo@vger.kernel.org More
> > >>>>> majordomo
> > >>>>>>>> info at  http://vger.kernel.org/majordomo-info.html
> > >>>>>>>>
> > >>>>>>
> > >>>>>> .
> > >>>>>>
> > >>>>>
> > >>>>
> > >>>>
> > >>>> .
> > >>>>
> > >>>
> > >>
> > >
> > > .
> > >
> >
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe devicetree"
> in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-07-17 10:45 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-03  8:35 [PATCH v2 0/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-06-03  8:35 ` [PATCH v2 1/4] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
2015-06-04 13:18   ` James Morse
2015-06-05  3:53     ` Zhou Wang
2015-06-03  8:35 ` [PATCH v2 2/4] PCI: designware: Add ARM64 support Zhou Wang
2015-06-04 13:19   ` James Morse
2015-06-05  8:11     ` Zhou Wang
2015-06-09 11:15       ` Lorenzo Pieralisi
2015-06-10 13:35         ` Gabriele Paoloni
2015-06-11  5:44           ` Zhou Wang
2015-06-11 14:32             ` Gabriele Paoloni
2015-06-16 11:30               ` Zhou Wang
2015-06-16 14:14                 ` Gabriele Paoloni
2015-07-13 10:58                   ` Lorenzo Pieralisi
2015-07-13 11:45                     ` Zhou Wang
2015-07-13 14:17                       ` Lorenzo Pieralisi
2015-07-17 10:45                         ` Gabriele Paoloni
2015-06-11  2:51         ` Zhou Wang
2015-06-11  2:44     ` Zhou Wang
2015-06-14 19:18   ` Pratyush Anand
2015-06-16 10:14     ` Zhou Wang
2015-06-03  8:35 ` [PATCH v2 3/4] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-06-04 13:23   ` James Morse
2015-06-05  8:13     ` Zhou Wang
2015-06-03  8:35 ` [PATCH v2 4/4] Documentation: DT: Add Hisilicon PCIe host binding Zhou Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).