All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-04-15  6:04 ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

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

Zhou Wang (3):
  PCI: host: designware: support ARM64
  PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
  Documentation: devicetree: Add hisilicon PCIe host binding

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-designware.c                 |  44 +++-
 drivers/pci/host/pcie-hisi.c                       | 252 +++++++++++++++++++++
 5 files changed, 345 insertions(+), 3 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] 21+ messages in thread

* [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-04-15  6:04 ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

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

Zhou Wang (3):
  PCI: host: designware: support ARM64
  PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
  Documentation: devicetree: Add hisilicon PCIe host binding

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-designware.c                 |  44 +++-
 drivers/pci/host/pcie-hisi.c                       | 252 +++++++++++++++++++++
 5 files changed, 345 insertions(+), 3 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] 21+ messages in thread

* [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-04-15  6:04 ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

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

Zhou Wang (3):
  PCI: host: designware: support ARM64
  PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
  Documentation: devicetree: Add hisilicon PCIe host binding

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-designware.c                 |  44 +++-
 drivers/pci/host/pcie-hisi.c                       | 252 +++++++++++++++++++++
 5 files changed, 345 insertions(+), 3 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] 21+ messages in thread

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
  2015-04-15  6:04 ` Zhou Wang
  (?)
@ 2015-04-15  6:04     ` Zhou Wang
  -1 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
	zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
	zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
	xiehaitao-hv44wF8Li93QT0dZR+AlfA,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q,
	wangzhou.bry-Re5JQEeQqe8AvxtiuMwx3w, Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
---
 drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 17ca986..e88a7d9 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -22,6 +22,7 @@
 #include <linux/pci_regs.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
+#include <asm/hardirq.h>
 
 #include "pcie-designware.h"
 
@@ -31,6 +32,7 @@
 #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
 #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
 #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
+#define PORT_LINK_MODE_8_LANES		(0xf << 16)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
 #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
@@ -38,6 +40,7 @@
 #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
 #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
 #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
+#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
 
 #define PCIE_MSI_ADDR_LO		0x820
 #define PCIE_MSI_ADDR_HI		0x824
@@ -68,14 +71,19 @@
 #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)
+static inline struct pcie_port *sys_to_pcie(void *sys)
 {
-	BUG_ON(!sys->private_data);
+#ifdef CONFIG_ARM
+	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
 
-	return sys->private_data;
+	BUG_ON(!sys->private_data);
+	return sys_data->private_data;
+#endif
+	return (struct pcie_port *)sys;
 }
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
@@ -502,6 +510,27 @@ int __init 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_ARM64
+	struct pci_bus *bus;
+	LIST_HEAD(res);
+
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+
+	pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
+#endif
+
+#ifdef CONFIG_ARM
 #ifdef CONFIG_PCI_MSI
 	dw_pcie_msi_chip.dev = pp->dev;
 	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
@@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 #ifdef CONFIG_PCI_DOMAINS
 	dw_pci.domain++;
 #endif
+#endif
 
 	return 0;
 }
@@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
+#ifdef CONFIG_ARM
 static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct pcie_port *pp;
@@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
 	.scan		= dw_pcie_scan_bus,
 	.map_irq	= dw_pcie_map_irq,
 };
+#endif
 
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
@@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LINK_MODE_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LINK_MODE_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
 
@@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
 
-- 
1.9.1

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

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

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-15  6:04     ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 17ca986..e88a7d9 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -22,6 +22,7 @@
 #include <linux/pci_regs.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
+#include <asm/hardirq.h>
 
 #include "pcie-designware.h"
 
@@ -31,6 +32,7 @@
 #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
 #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
 #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
+#define PORT_LINK_MODE_8_LANES		(0xf << 16)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
 #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
@@ -38,6 +40,7 @@
 #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
 #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
 #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
+#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
 
 #define PCIE_MSI_ADDR_LO		0x820
 #define PCIE_MSI_ADDR_HI		0x824
@@ -68,14 +71,19 @@
 #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)
+static inline struct pcie_port *sys_to_pcie(void *sys)
 {
-	BUG_ON(!sys->private_data);
+#ifdef CONFIG_ARM
+	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
 
-	return sys->private_data;
+	BUG_ON(!sys->private_data);
+	return sys_data->private_data;
+#endif
+	return (struct pcie_port *)sys;
 }
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
@@ -502,6 +510,27 @@ int __init 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_ARM64
+	struct pci_bus *bus;
+	LIST_HEAD(res);
+
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+
+	pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
+#endif
+
+#ifdef CONFIG_ARM
 #ifdef CONFIG_PCI_MSI
 	dw_pcie_msi_chip.dev = pp->dev;
 	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
@@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 #ifdef CONFIG_PCI_DOMAINS
 	dw_pci.domain++;
 #endif
+#endif
 
 	return 0;
 }
@@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
+#ifdef CONFIG_ARM
 static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct pcie_port *pp;
@@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
 	.scan		= dw_pcie_scan_bus,
 	.map_irq	= dw_pcie_map_irq,
 };
+#endif
 
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
@@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LINK_MODE_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LINK_MODE_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
 
@@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
 
-- 
1.9.1


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

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-15  6:04     ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 17ca986..e88a7d9 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -22,6 +22,7 @@
 #include <linux/pci_regs.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
+#include <asm/hardirq.h>
 
 #include "pcie-designware.h"
 
@@ -31,6 +32,7 @@
 #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
 #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
 #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
+#define PORT_LINK_MODE_8_LANES		(0xf << 16)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
 #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
@@ -38,6 +40,7 @@
 #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
 #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
 #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
+#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
 
 #define PCIE_MSI_ADDR_LO		0x820
 #define PCIE_MSI_ADDR_HI		0x824
@@ -68,14 +71,19 @@
 #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)
+static inline struct pcie_port *sys_to_pcie(void *sys)
 {
-	BUG_ON(!sys->private_data);
+#ifdef CONFIG_ARM
+	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
 
-	return sys->private_data;
+	BUG_ON(!sys->private_data);
+	return sys_data->private_data;
+#endif
+	return (struct pcie_port *)sys;
 }
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
@@ -502,6 +510,27 @@ int __init 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_ARM64
+	struct pci_bus *bus;
+	LIST_HEAD(res);
+
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
+
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+
+	pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
+#endif
+
+#ifdef CONFIG_ARM
 #ifdef CONFIG_PCI_MSI
 	dw_pcie_msi_chip.dev = pp->dev;
 	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
@@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 #ifdef CONFIG_PCI_DOMAINS
 	dw_pci.domain++;
 #endif
+#endif
 
 	return 0;
 }
@@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
+#ifdef CONFIG_ARM
 static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct pcie_port *pp;
@@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
 	.scan		= dw_pcie_scan_bus,
 	.map_irq	= dw_pcie_map_irq,
 };
+#endif
 
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
@@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LINK_MODE_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LINK_MODE_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
 
@@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	case 4:
 		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
 		break;
+	case 8:
+		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
+		break;
 	}
 	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
 
-- 
1.9.1

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

* [RFC PATCH 2/3] PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
  2015-04-15  6:04 ` Zhou Wang
  (?)
@ 2015-04-15  6:04     ` Zhou Wang
  -1 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
	zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
	zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
	xiehaitao-hv44wF8Li93QT0dZR+AlfA,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q,
	wangzhou.bry-Re5JQEeQqe8AvxtiuMwx3w, Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
---
 drivers/pci/host/Kconfig     |   5 +
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 252 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c4b6568..229f418 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -102,4 +102,9 @@ config PCI_LAYERSCAPE
 	help
 	  Say Y here if you want PCIe controller support on Layerscape SoCs.
 
+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 44c2699..154f406 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.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..3f8cb9a
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,252 @@
+/*
+ * PCIe host controller driver for Hisilicon Hip05 SoCs
+ *
+ * Copyright (C) 2014 Hisilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
+ *         Dacai Zhu <zhudacai-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
+ *
+ * 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_LTSSM_LINKUP_STATE                         (0x11)
+#define PCIE_LTSSM_STATE_MASK                           (0x3F)
+#define PCIE_MSI_CONTEXT_VALUE                          (0x1011000)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1ff0)
+#define PCIE_MSI_LOW_ADDRESS                            (0x1b4)
+#define PCIE_MSI_HIGH_ADDRESS                           (0x1c4)
+
+#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);
+
+	for (i = 0; i < 0x400; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	for (i = 0x400; 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, 0xb7010040, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_CONTEXT_VALUE, 0x10);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, 0x1c8);
+
+	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-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>");
+MODULE_AUTHOR("Dacai Zhu <zhudacai-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

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

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

* [RFC PATCH 2/3] PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-04-15  6:04     ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/Kconfig     |   5 +
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 252 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c4b6568..229f418 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -102,4 +102,9 @@ config PCI_LAYERSCAPE
 	help
 	  Say Y here if you want PCIe controller support on Layerscape SoCs.
 
+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 44c2699..154f406 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.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..3f8cb9a
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,252 @@
+/*
+ * PCIe host controller driver for Hisilicon Hip05 SoCs
+ *
+ * Copyright (C) 2014 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_LTSSM_LINKUP_STATE                         (0x11)
+#define PCIE_LTSSM_STATE_MASK                           (0x3F)
+#define PCIE_MSI_CONTEXT_VALUE                          (0x1011000)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1ff0)
+#define PCIE_MSI_LOW_ADDRESS                            (0x1b4)
+#define PCIE_MSI_HIGH_ADDRESS                           (0x1c4)
+
+#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);
+
+	for (i = 0; i < 0x400; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	for (i = 0x400; 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, 0xb7010040, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_CONTEXT_VALUE, 0x10);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, 0x1c8);
+
+	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] 21+ messages in thread

* [RFC PATCH 2/3] PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-04-15  6:04     ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/Kconfig     |   5 +
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 252 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c4b6568..229f418 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -102,4 +102,9 @@ config PCI_LAYERSCAPE
 	help
 	  Say Y here if you want PCIe controller support on Layerscape SoCs.
 
+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 44c2699..154f406 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.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..3f8cb9a
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,252 @@
+/*
+ * PCIe host controller driver for Hisilicon Hip05 SoCs
+ *
+ * Copyright (C) 2014 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_LTSSM_LINKUP_STATE                         (0x11)
+#define PCIE_LTSSM_STATE_MASK                           (0x3F)
+#define PCIE_MSI_CONTEXT_VALUE                          (0x1011000)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1ff0)
+#define PCIE_MSI_LOW_ADDRESS                            (0x1b4)
+#define PCIE_MSI_HIGH_ADDRESS                           (0x1c4)
+
+#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);
+
+	for (i = 0; i < 0x400; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	for (i = 0x400; 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, 0xb7010040, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_CONTEXT_VALUE, 0x10);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, 0x1c8);
+
+	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] 21+ messages in thread

* [RFC PATCH 3/3] Documentation: devicetree: Add hisilicon PCIe host binding
  2015-04-15  6:04 ` Zhou Wang
  (?)
@ 2015-04-15  6:04   ` Zhou Wang
  -1 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

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..c24578d
--- /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 0x1000>;
+		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 0xb4100000 0x220 0x00100000 0 0x00f00000>;
+		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] 21+ messages in thread

* [RFC PATCH 3/3] Documentation: devicetree: Add hisilicon PCIe host binding
@ 2015-04-15  6:04   ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau
  Cc: linux-pci, linux-arm-kernel, devicetree, gabriele.paoloni,
	yuanzhichang, zhudacai, zhangjukuo, xiehaitao, liguozhu,
	wangzhou.bry, Zhou Wang

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..c24578d
--- /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 0x1000>;
+		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 0xb4100000 0x220 0x00100000 0 0x00f00000>;
+		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] 21+ messages in thread

* [RFC PATCH 3/3] Documentation: devicetree: Add hisilicon PCIe host binding
@ 2015-04-15  6:04   ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-15  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

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..c24578d
--- /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 at 0xb0080000 {
+		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+		reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+		      <0x220 0x00000000 0 0x1000>;
+		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 0xb4100000 0x220 0x00100000 0 0x00f00000>;
+		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] 21+ messages in thread

* Re: [RFC PATCH 1/3] PCI: host: designware: support ARM64
  2015-04-15  6:04     ` Zhou Wang
@ 2015-04-15 10:04       ` Arnd Bergmann
  -1 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2015-04-15 10:04 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, xiehaitao, liguozhu, wangzhou.bry

On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>

Please provide a changelog with every patch you do

> ---
>  drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 17ca986..e88a7d9 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -31,6 +32,7 @@
>  #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
>  #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
>  #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
> +#define PORT_LINK_MODE_8_LANES		(0xf << 16)
>  
>  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
>  #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
>
> @@ -38,6 +40,7 @@
>  #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
>  #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
>  #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
> +#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
>  
>  #define PCIE_MSI_ADDR_LO		0x820
>  #define PCIE_MSI_ADDR_HI		0x824

This seems unrelated to arm64 support, so put that in a separate patch


> @@ -68,14 +71,19 @@
>  #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)
> +static inline struct pcie_port *sys_to_pcie(void *sys)
>  {
> -	BUG_ON(!sys->private_data);
> +#ifdef CONFIG_ARM
> +	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
>  
> -	return sys->private_data;
> +	BUG_ON(!sys->private_data);
> +	return sys_data->private_data;
> +#endif
> +	return (struct pcie_port *)sys;
>  }
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)

Yes, I guess this is the best workaround for now, and we should be able to
drop that arm32 specific section soon.

> @@ -502,6 +510,27 @@ int __init 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_ARM64
> +	struct pci_bus *bus;
> +	LIST_HEAD(res);
> +
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
> +
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +
> +	pci_scan_child_bus(bus);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
> +#endif
> +
> +#ifdef CONFIG_ARM
>  #ifdef CONFIG_PCI_MSI
>  	dw_pcie_msi_chip.dev = pp->dev;
>  	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> @@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>  #ifdef CONFIG_PCI_DOMAINS
>  	dw_pci.domain++;
>  #endif
> +#endif
>  

I think here we should move everything to the new model and do it the
same way on ARM, except for setting the sysdata pointer.

> @@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> +#ifdef CONFIG_ARM
>  static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>  {
>  	struct pcie_port *pp;
> @@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
>  	.scan		= dw_pcie_scan_bus,
>  	.map_irq	= dw_pcie_map_irq,
>  };
> +#endif
>  
>  void dw_pcie_setup_rc(struct pcie_port *pp)

Same here, just remove the dw_pcie_setup function and dw_pci structure
and use the arm64 implementation.

> @@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>  	case 4:
>  		val |= PORT_LINK_MODE_4_LANES;
>  		break;
> +	case 8:
> +		val |= PORT_LINK_MODE_8_LANES;
> +		break;
>  	}
>  	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
>  
> @@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>  	case 4:
>  		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
>  		break;
> +	case 8:
> +		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
> +		break;
>  	}
>  	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);

Again, separate patch.

I've just tried to come up with a nicer way of doing all this, can
you try the experimental patch below?

	Arnd

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84fdd9ce..4ef2ca8e3404 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -67,7 +67,7 @@
 #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;
 
@@ -238,7 +238,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 +281,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 +310,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);
 }
@@ -348,7 +348,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	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 +504,42 @@ 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;
-#endif
+#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) {
+		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(&res, &pp->mem, sys->mem_offset);
+	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;
+
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
+
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
 
-	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);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +682,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 +706,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 +730,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 d0bbd276840d..be7e4b72fbfc 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -23,6 +23,15 @@
 #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
 
 struct pcie_port {
+#ifdef CONFIG_ARM
+	/*
+	 * this is a temporary hack to let the driver work on
+	 * both arm32 and arm64. it can be removed after the
+	 * arm32 cleanup is complete and bios32.c has stopped
+	 * referencing host->pci_sys_data.
+	 */
+	struct pci_sys_data	dummy;
+#endif
 	struct device		*dev;
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;

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

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-15 10:04       ` Arnd Bergmann
  0 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2015-04-15 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>

Please provide a changelog with every patch you do

> ---
>  drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 17ca986..e88a7d9 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -31,6 +32,7 @@
>  #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
>  #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
>  #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
> +#define PORT_LINK_MODE_8_LANES		(0xf << 16)
>  
>  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
>  #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
>
> @@ -38,6 +40,7 @@
>  #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
>  #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
>  #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
> +#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
>  
>  #define PCIE_MSI_ADDR_LO		0x820
>  #define PCIE_MSI_ADDR_HI		0x824

This seems unrelated to arm64 support, so put that in a separate patch


> @@ -68,14 +71,19 @@
>  #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)
> +static inline struct pcie_port *sys_to_pcie(void *sys)
>  {
> -	BUG_ON(!sys->private_data);
> +#ifdef CONFIG_ARM
> +	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
>  
> -	return sys->private_data;
> +	BUG_ON(!sys->private_data);
> +	return sys_data->private_data;
> +#endif
> +	return (struct pcie_port *)sys;
>  }
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)

Yes, I guess this is the best workaround for now, and we should be able to
drop that arm32 specific section soon.

> @@ -502,6 +510,27 @@ int __init 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_ARM64
> +	struct pci_bus *bus;
> +	LIST_HEAD(res);
> +
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
> +
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +
> +	pci_scan_child_bus(bus);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
> +#endif
> +
> +#ifdef CONFIG_ARM
>  #ifdef CONFIG_PCI_MSI
>  	dw_pcie_msi_chip.dev = pp->dev;
>  	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> @@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>  #ifdef CONFIG_PCI_DOMAINS
>  	dw_pci.domain++;
>  #endif
> +#endif
>  

I think here we should move everything to the new model and do it the
same way on ARM, except for setting the sysdata pointer.

> @@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> +#ifdef CONFIG_ARM
>  static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>  {
>  	struct pcie_port *pp;
> @@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
>  	.scan		= dw_pcie_scan_bus,
>  	.map_irq	= dw_pcie_map_irq,
>  };
> +#endif
>  
>  void dw_pcie_setup_rc(struct pcie_port *pp)

Same here, just remove the dw_pcie_setup function and dw_pci structure
and use the arm64 implementation.

> @@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>  	case 4:
>  		val |= PORT_LINK_MODE_4_LANES;
>  		break;
> +	case 8:
> +		val |= PORT_LINK_MODE_8_LANES;
> +		break;
>  	}
>  	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
>  
> @@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>  	case 4:
>  		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
>  		break;
> +	case 8:
> +		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
> +		break;
>  	}
>  	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);

Again, separate patch.

I've just tried to come up with a nicer way of doing all this, can
you try the experimental patch below?

	Arnd

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84fdd9ce..4ef2ca8e3404 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -67,7 +67,7 @@
 #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;
 
@@ -238,7 +238,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 +281,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 +310,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);
 }
@@ -348,7 +348,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	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 +504,42 @@ 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;
-#endif
+#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) {
+		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(&res, &pp->mem, sys->mem_offset);
+	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;
+
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
+
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
 
-	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);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -653,7 +682,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 +706,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 +730,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 d0bbd276840d..be7e4b72fbfc 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -23,6 +23,15 @@
 #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
 
 struct pcie_port {
+#ifdef CONFIG_ARM
+	/*
+	 * this is a temporary hack to let the driver work on
+	 * both arm32 and arm64. it can be removed after the
+	 * arm32 cleanup is complete and bios32.c has stopped
+	 * referencing host->pci_sys_data.
+	 */
+	struct pci_sys_data	dummy;
+#endif
 	struct device		*dev;
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;

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

* Re: [RFC PATCH 1/3] PCI: host: designware: support ARM64
  2015-04-15 10:04       ` Arnd Bergmann
  (?)
@ 2015-04-16  5:51         ` Zhou Wang
  -1 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-16  5:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Liviu Dudau,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
	zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
	zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
	xiehaitao-hv44wF8Li93QT0dZR+AlfA,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q,
	wangzhou.bry-Re5JQEeQqe8AvxtiuMwx3w

On 2015/4/15 18:04, Arnd Bergmann wrote:
> On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
>> Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> 
> Please provide a changelog with every patch you do

Will add the related changelog next version.

> 
>> ---
>>  drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
>>  1 file changed, 41 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 17ca986..e88a7d9 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -31,6 +32,7 @@
>>  #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
>>  #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
>>  #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
>> +#define PORT_LINK_MODE_8_LANES		(0xf << 16)
>>  
>>  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
>>  #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
>>
>> @@ -38,6 +40,7 @@
>>  #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
>> +#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
>>  
>>  #define PCIE_MSI_ADDR_LO		0x820
>>  #define PCIE_MSI_ADDR_HI		0x824
> 
> This seems unrelated to arm64 support, so put that in a separate patch
> 
> 

Yes, I will put the PCIe X8 support code in another patch.

>> @@ -68,14 +71,19 @@
>>  #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)
>> +static inline struct pcie_port *sys_to_pcie(void *sys)
>>  {
>> -	BUG_ON(!sys->private_data);
>> +#ifdef CONFIG_ARM
>> +	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
>>  
>> -	return sys->private_data;
>> +	BUG_ON(!sys->private_data);
>> +	return sys_data->private_data;
>> +#endif
>> +	return (struct pcie_port *)sys;
>>  }
>>  
>>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
> 
> Yes, I guess this is the best workaround for now, and we should be able to
> drop that arm32 specific section soon.
> 
>> @@ -502,6 +510,27 @@ int __init 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_ARM64
>> +	struct pci_bus *bus;
>> +	LIST_HEAD(res);
>> +
>> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
>> +	if (ret)
>> +		return ret;
>> +
>> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
>> +				  pp, &res);
>> +	if (!bus)
>> +		return -ENOMEM;
>> +
>> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>> +
>> +	pci_scan_child_bus(bus);
>> +	pci_assign_unassigned_bus_resources(bus);
>> +	pci_bus_add_devices(bus);
>> +#endif
>> +
>> +#ifdef CONFIG_ARM
>>  #ifdef CONFIG_PCI_MSI
>>  	dw_pcie_msi_chip.dev = pp->dev;
>>  	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
>> @@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>>  #ifdef CONFIG_PCI_DOMAINS
>>  	dw_pci.domain++;
>>  #endif
>> +#endif
>>  
> 
> I think here we should move everything to the new model and do it the
> same way on ARM, except for setting the sysdata pointer.
> 
>> @@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
>>  	.write = dw_pcie_wr_conf,
>>  };
>>  
>> +#ifdef CONFIG_ARM
>>  static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>>  {
>>  	struct pcie_port *pp;
>> @@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
>>  	.scan		= dw_pcie_scan_bus,
>>  	.map_irq	= dw_pcie_map_irq,
>>  };
>> +#endif
>>  
>>  void dw_pcie_setup_rc(struct pcie_port *pp)
> 
> Same here, just remove the dw_pcie_setup function and dw_pci structure
> and use the arm64 implementation.
> 
>> @@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LINK_MODE_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LINK_MODE_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
>>  
>> @@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
> 
> Again, separate patch.
> 
> I've just tried to come up with a nicer way of doing all this, can
> you try the experimental patch below?
> 
> 	Arnd
> 

Sure, I will try the patch below. I think it can work well in my Hisilicon
D02 board. But I don't have arm32 PCIe related board to test. It will be helpful
if someone could help to test it.

Thanks for your comments, Arnd.

Regards,
Zhou

> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84fdd9ce..4ef2ca8e3404 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -67,7 +67,7 @@
>  #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;
>  
> @@ -238,7 +238,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 +281,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 +310,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);
>  }
> @@ -348,7 +348,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	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 +504,42 @@ 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;
> -#endif
> +#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) {
> +		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(&res, &pp->mem, sys->mem_offset);
> +	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;
> +
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> +
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>  
> -	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);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -653,7 +682,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 +706,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 +730,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 d0bbd276840d..be7e4b72fbfc 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -23,6 +23,15 @@
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
>  
>  struct pcie_port {
> +#ifdef CONFIG_ARM
> +	/*
> +	 * this is a temporary hack to let the driver work on
> +	 * both arm32 and arm64. it can be removed after the
> +	 * arm32 cleanup is complete and bios32.c has stopped
> +	 * referencing host->pci_sys_data.
> +	 */
> +	struct pci_sys_data	dummy;
> +#endif
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
> 
> 
> .
> 


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

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

* Re: [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-16  5:51         ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-16  5:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, xiehaitao, liguozhu, wangzhou.bry

On 2015/4/15 18:04, Arnd Bergmann wrote:
> On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
>> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> 
> Please provide a changelog with every patch you do

Will add the related changelog next version.

> 
>> ---
>>  drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
>>  1 file changed, 41 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 17ca986..e88a7d9 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -31,6 +32,7 @@
>>  #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
>>  #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
>>  #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
>> +#define PORT_LINK_MODE_8_LANES		(0xf << 16)
>>  
>>  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
>>  #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
>>
>> @@ -38,6 +40,7 @@
>>  #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
>> +#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
>>  
>>  #define PCIE_MSI_ADDR_LO		0x820
>>  #define PCIE_MSI_ADDR_HI		0x824
> 
> This seems unrelated to arm64 support, so put that in a separate patch
> 
> 

Yes, I will put the PCIe X8 support code in another patch.

>> @@ -68,14 +71,19 @@
>>  #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)
>> +static inline struct pcie_port *sys_to_pcie(void *sys)
>>  {
>> -	BUG_ON(!sys->private_data);
>> +#ifdef CONFIG_ARM
>> +	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
>>  
>> -	return sys->private_data;
>> +	BUG_ON(!sys->private_data);
>> +	return sys_data->private_data;
>> +#endif
>> +	return (struct pcie_port *)sys;
>>  }
>>  
>>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
> 
> Yes, I guess this is the best workaround for now, and we should be able to
> drop that arm32 specific section soon.
> 
>> @@ -502,6 +510,27 @@ int __init 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_ARM64
>> +	struct pci_bus *bus;
>> +	LIST_HEAD(res);
>> +
>> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
>> +	if (ret)
>> +		return ret;
>> +
>> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
>> +				  pp, &res);
>> +	if (!bus)
>> +		return -ENOMEM;
>> +
>> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>> +
>> +	pci_scan_child_bus(bus);
>> +	pci_assign_unassigned_bus_resources(bus);
>> +	pci_bus_add_devices(bus);
>> +#endif
>> +
>> +#ifdef CONFIG_ARM
>>  #ifdef CONFIG_PCI_MSI
>>  	dw_pcie_msi_chip.dev = pp->dev;
>>  	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
>> @@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>>  #ifdef CONFIG_PCI_DOMAINS
>>  	dw_pci.domain++;
>>  #endif
>> +#endif
>>  
> 
> I think here we should move everything to the new model and do it the
> same way on ARM, except for setting the sysdata pointer.
> 
>> @@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
>>  	.write = dw_pcie_wr_conf,
>>  };
>>  
>> +#ifdef CONFIG_ARM
>>  static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>>  {
>>  	struct pcie_port *pp;
>> @@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
>>  	.scan		= dw_pcie_scan_bus,
>>  	.map_irq	= dw_pcie_map_irq,
>>  };
>> +#endif
>>  
>>  void dw_pcie_setup_rc(struct pcie_port *pp)
> 
> Same here, just remove the dw_pcie_setup function and dw_pci structure
> and use the arm64 implementation.
> 
>> @@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LINK_MODE_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LINK_MODE_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
>>  
>> @@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
> 
> Again, separate patch.
> 
> I've just tried to come up with a nicer way of doing all this, can
> you try the experimental patch below?
> 
> 	Arnd
> 

Sure, I will try the patch below. I think it can work well in my Hisilicon
D02 board. But I don't have arm32 PCIe related board to test. It will be helpful
if someone could help to test it.

Thanks for your comments, Arnd.

Regards,
Zhou

> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84fdd9ce..4ef2ca8e3404 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -67,7 +67,7 @@
>  #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;
>  
> @@ -238,7 +238,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 +281,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 +310,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);
>  }
> @@ -348,7 +348,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	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 +504,42 @@ 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;
> -#endif
> +#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) {
> +		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(&res, &pp->mem, sys->mem_offset);
> +	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;
> +
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> +
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>  
> -	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);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -653,7 +682,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 +706,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 +730,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 d0bbd276840d..be7e4b72fbfc 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -23,6 +23,15 @@
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
>  
>  struct pcie_port {
> +#ifdef CONFIG_ARM
> +	/*
> +	 * this is a temporary hack to let the driver work on
> +	 * both arm32 and arm64. it can be removed after the
> +	 * arm32 cleanup is complete and bios32.c has stopped
> +	 * referencing host->pci_sys_data.
> +	 */
> +	struct pci_sys_data	dummy;
> +#endif
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
> 
> 
> .
> 



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

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-16  5:51         ` Zhou Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Zhou Wang @ 2015-04-16  5:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015/4/15 18:04, Arnd Bergmann wrote:
> On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
>> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> 
> Please provide a changelog with every patch you do

Will add the related changelog next version.

> 
>> ---
>>  drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++---
>>  1 file changed, 41 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
>> index 17ca986..e88a7d9 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -31,6 +32,7 @@
>>  #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
>>  #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
>>  #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
>> +#define PORT_LINK_MODE_8_LANES		(0xf << 16)
>>  
>>  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
>>  #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
>>
>> @@ -38,6 +40,7 @@
>>  #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
>>  #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
>> +#define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
>>  
>>  #define PCIE_MSI_ADDR_LO		0x820
>>  #define PCIE_MSI_ADDR_HI		0x824
> 
> This seems unrelated to arm64 support, so put that in a separate patch
> 
> 

Yes, I will put the PCIe X8 support code in another patch.

>> @@ -68,14 +71,19 @@
>>  #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)
>> +static inline struct pcie_port *sys_to_pcie(void *sys)
>>  {
>> -	BUG_ON(!sys->private_data);
>> +#ifdef CONFIG_ARM
>> +	pci_sys_data *sys_data = (struct pci_sys_data *)sys;
>>  
>> -	return sys->private_data;
>> +	BUG_ON(!sys->private_data);
>> +	return sys_data->private_data;
>> +#endif
>> +	return (struct pcie_port *)sys;
>>  }
>>  
>>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
> 
> Yes, I guess this is the best workaround for now, and we should be able to
> drop that arm32 specific section soon.
> 
>> @@ -502,6 +510,27 @@ int __init 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_ARM64
>> +	struct pci_bus *bus;
>> +	LIST_HEAD(res);
>> +
>> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
>> +	if (ret)
>> +		return ret;
>> +
>> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
>> +				  pp, &res);
>> +	if (!bus)
>> +		return -ENOMEM;
>> +
>> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>> +
>> +	pci_scan_child_bus(bus);
>> +	pci_assign_unassigned_bus_resources(bus);
>> +	pci_bus_add_devices(bus);
>> +#endif
>> +
>> +#ifdef CONFIG_ARM
>>  #ifdef CONFIG_PCI_MSI
>>  	dw_pcie_msi_chip.dev = pp->dev;
>>  	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
>> @@ -514,6 +543,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>>  #ifdef CONFIG_PCI_DOMAINS
>>  	dw_pci.domain++;
>>  #endif
>> +#endif
>>  
> 
> I think here we should move everything to the new model and do it the
> same way on ARM, except for setting the sysdata pointer.
> 
>> @@ -704,6 +734,7 @@ static struct pci_ops dw_pcie_ops = {
>>  	.write = dw_pcie_wr_conf,
>>  };
>>  
>> +#ifdef CONFIG_ARM
>>  static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>>  {
>>  	struct pcie_port *pp;
>> @@ -761,6 +792,7 @@ static struct hw_pci dw_pci = {
>>  	.scan		= dw_pcie_scan_bus,
>>  	.map_irq	= dw_pcie_map_irq,
>>  };
>> +#endif
>>  
>>  void dw_pcie_setup_rc(struct pcie_port *pp)
> 
> Same here, just remove the dw_pcie_setup function and dw_pci structure
> and use the arm64 implementation.
> 
>> @@ -781,6 +813,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LINK_MODE_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LINK_MODE_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
>>  
>> @@ -797,6 +832,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
>>  	case 4:
>>  		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
>>  		break;
>> +	case 8:
>> +		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
>> +		break;
>>  	}
>>  	dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
> 
> Again, separate patch.
> 
> I've just tried to come up with a nicer way of doing all this, can
> you try the experimental patch below?
> 
> 	Arnd
> 

Sure, I will try the patch below. I think it can work well in my Hisilicon
D02 board. But I don't have arm32 PCIe related board to test. It will be helpful
if someone could help to test it.

Thanks for your comments, Arnd.

Regards,
Zhou

> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 2e9f84fdd9ce..4ef2ca8e3404 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -67,7 +67,7 @@
>  #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;
>  
> @@ -238,7 +238,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 +281,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 +310,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);
>  }
> @@ -348,7 +348,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	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 +504,42 @@ 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;
> -#endif
> +#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) {
> +		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(&res, &pp->mem, sys->mem_offset);
> +	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;
> +
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> +
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
>  
> -	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);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -653,7 +682,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 +706,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 +730,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 d0bbd276840d..be7e4b72fbfc 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -23,6 +23,15 @@
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
>  
>  struct pcie_port {
> +#ifdef CONFIG_ARM
> +	/*
> +	 * this is a temporary hack to let the driver work on
> +	 * both arm32 and arm64. it can be removed after the
> +	 * arm32 cleanup is complete and bios32.c has stopped
> +	 * referencing host->pci_sys_data.
> +	 */
> +	struct pci_sys_data	dummy;
> +#endif
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
> 
> 
> .
> 

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

* Re: [RFC PATCH 1/3] PCI: host: designware: support ARM64
  2015-04-16  5:51         ` Zhou Wang
@ 2015-04-16  8:00           ` Arnd Bergmann
  -1 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2015-04-16  8:00 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, Mohit Kumar, Jingoo Han, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, xiehaitao, liguozhu, wangzhou.bry

On Thursday 16 April 2015 13:51:47 Zhou Wang wrote:
> > 
> > Again, separate patch.
> > 
> > I've just tried to come up with a nicer way of doing all this, can
> > you try the experimental patch below?
> > 
> >       Arnd
> > 
> 
> Sure, I will try the patch below. I think it can work well in my Hisilicon
> D02 board. But I don't have arm32 PCIe related board to test. It will be helpful
> if someone could help to test it.

Ok, please incorporate the patch into your series then and make sure it
builds fine on both 32-bit (multi_v7_defconfig) and 64-bit ARM. If we
get consensus on the code, I'm sure we can find testers.

	Arnd

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

* [RFC PATCH 1/3] PCI: host: designware: support ARM64
@ 2015-04-16  8:00           ` Arnd Bergmann
  0 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2015-04-16  8:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 16 April 2015 13:51:47 Zhou Wang wrote:
> > 
> > Again, separate patch.
> > 
> > I've just tried to come up with a nicer way of doing all this, can
> > you try the experimental patch below?
> > 
> >       Arnd
> > 
> 
> Sure, I will try the patch below. I think it can work well in my Hisilicon
> D02 board. But I don't have arm32 PCIe related board to test. It will be helpful
> if someone could help to test it.

Ok, please incorporate the patch into your series then and make sure it
builds fine on both 32-bit (multi_v7_defconfig) and 64-bit ARM. If we
get consensus on the code, I'm sure we can find testers.

	Arnd

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

* Re: [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05
  2015-04-15  6:04 ` Zhou Wang
@ 2015-05-07 15:24   ` Bjorn Helgaas
  -1 siblings, 0 replies; 21+ messages in thread
From: Bjorn Helgaas @ 2015-05-07 15:24 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Mohit Kumar, Jingoo Han, Arnd Bergmann, Liviu Dudau, linux-pci,
	linux-arm-kernel, devicetree, gabriele.paoloni, yuanzhichang,
	zhudacai, zhangjukuo, xiehaitao, liguozhu, wangzhou.bry

On Wed, Apr 15, 2015 at 02:04:00PM +0800, Zhou Wang wrote:
> This patchset adds PCIe host support for Hisilicon Soc Hip05. The PCIe hosts
> use PCIe IP core from Synopsys. So the driver is based on designware PCIe driver.
> 
> Zhou Wang (3):
>   PCI: host: designware: support ARM64
>   PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
>   Documentation: devicetree: Add hisilicon PCIe host binding

Please run "git log" and "git log --oneline" on each file you change, and
make your changelogs and summaries look like the rest -- same style, same
capitalization, etc.

>  .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
>  drivers/pci/host/Kconfig                           |   5 +
>  drivers/pci/host/Makefile                          |   1 +
>  drivers/pci/host/pcie-designware.c                 |  44 +++-
>  drivers/pci/host/pcie-hisi.c                       | 252 +++++++++++++++++++++
>  5 files changed, 345 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
>  create mode 100644 drivers/pci/host/pcie-hisi.c
> 
> -- 
> 1.9.1
> 
> --
> 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] 21+ messages in thread

* [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05
@ 2015-05-07 15:24   ` Bjorn Helgaas
  0 siblings, 0 replies; 21+ messages in thread
From: Bjorn Helgaas @ 2015-05-07 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 15, 2015 at 02:04:00PM +0800, Zhou Wang wrote:
> This patchset adds PCIe host support for Hisilicon Soc Hip05. The PCIe hosts
> use PCIe IP core from Synopsys. So the driver is based on designware PCIe driver.
> 
> Zhou Wang (3):
>   PCI: host: designware: support ARM64
>   PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
>   Documentation: devicetree: Add hisilicon PCIe host binding

Please run "git log" and "git log --oneline" on each file you change, and
make your changelogs and summaries look like the rest -- same style, same
capitalization, etc.

>  .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
>  drivers/pci/host/Kconfig                           |   5 +
>  drivers/pci/host/Makefile                          |   1 +
>  drivers/pci/host/pcie-designware.c                 |  44 +++-
>  drivers/pci/host/pcie-hisi.c                       | 252 +++++++++++++++++++++
>  5 files changed, 345 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
>  create mode 100644 drivers/pci/host/pcie-hisi.c
> 
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2015-05-07 15:24 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-15  6:04 [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-04-15  6:04 ` Zhou Wang
2015-04-15  6:04 ` Zhou Wang
     [not found] ` <1429077843-184462-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
2015-04-15  6:04   ` [RFC PATCH 1/3] PCI: host: designware: support ARM64 Zhou Wang
2015-04-15  6:04     ` Zhou Wang
2015-04-15  6:04     ` Zhou Wang
2015-04-15 10:04     ` Arnd Bergmann
2015-04-15 10:04       ` Arnd Bergmann
2015-04-16  5:51       ` Zhou Wang
2015-04-16  5:51         ` Zhou Wang
2015-04-16  5:51         ` Zhou Wang
2015-04-16  8:00         ` Arnd Bergmann
2015-04-16  8:00           ` Arnd Bergmann
2015-04-15  6:04   ` [RFC PATCH 2/3] PCI: Host: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-04-15  6:04     ` Zhou Wang
2015-04-15  6:04     ` Zhou Wang
2015-04-15  6:04 ` [RFC PATCH 3/3] Documentation: devicetree: Add hisilicon PCIe host binding Zhou Wang
2015-04-15  6:04   ` Zhou Wang
2015-04-15  6:04   ` Zhou Wang
2015-05-07 15:24 ` [RFC PATCH 0/3] PCI: host: Add PCIe host support for Hisilicon Soc Hip05 Bjorn Helgaas
2015-05-07 15:24   ` Bjorn Helgaas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.