PCI: host: Add PCIe host support for Hisilicon Soc Hip05
cover PCI: host: Add PCIe host support for Hisilicon Soc Hip05
This patchset adds PCIe host support for Hisilicon Soc Hip05. The PCIe hosts use PCIe IP core from Synopsys. So 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
Signature · 1 line
1.9.1
RFC PATCH 1/3 PCI: host: designware: support ARM64
--- drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)
drivers/pci/host/pcie-designware.c +41 -3
@@ -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 0x91Cstatic 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 );
Signature · 1 line
1.9.1
RFC PATCH 1/3 PCI: host: designware: support ARM64
Quoted 1 line · On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
Signed-off-by Zhou Wang <[email protected]>
Please provide a changelog with every patch you do
Quoted 18 lines
--- drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)drivers/pci/host/pcie-designware.c +1
-0@@ -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)
drivers/pci/host/pcie-designware.c line 46
Quoted 7 lines
drivers/pci/host/pcie-designware.c +1
-0@@ -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
Quoted 13 lines
drivers/pci/host/pcie-designware.c +3
-2@@ -68,14 +71,19 @@#define PCIE_ATU_UPPER_TARGET 0x91Cstatic 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
drivers/pci/host/pcie-designware.c line 89
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5
-1+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.
Quoted 29 lines
drivers/pci/host/pcie-designware.c +21
-0@@ -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;
drivers/pci/host/pcie-designware.c int __init dw_pcie_host_init(struct pcie_port *pp) · line 547
Quoted 5 lines
drivers/pci/host/pcie-designware.c +1
-0@@ -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.
Quoted 9 lines
drivers/pci/host/pcie-designware.c +1
-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;
drivers/pci/host/pcie-designware.c static struct hw_pci dw_pci = { · line 797
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1
-0@@ -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.
Quoted 11 lines
drivers/pci/host/pcie-designware.c +3
-0@@ -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 );
drivers/pci/host/pcie-designware.c void dw_pcie_setup_rc(struct pcie_port *pp) · line 839
Quoted 8 lines
drivers/pci/host/pcie-designware.c +3
-0@@ -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
drivers/pci/host/pcie-designware.c +42 -71
@@ -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;
drivers/pci/host/pcie-designware.h +9 -0
@@ -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;
RFC PATCH 1/3 PCI: host: designware: support ARM64
Quoted 4 lines · Arnd Bergmann
Quoted 1 line · On Wednesday 15 April 2015 14:04:01 Zhou Wang wrote:
Signed-off-by Zhou Wang <[email protected]>Please provide a changelog with every patch you do
Will add the related changelog next version.
Quoted 24 lines
Quoted 24 lines
--- drivers/pci/host/pcie-designware.c | 44 +++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)drivers/pci/host/pcie-designware.c +2
-0@@ -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)
Quoted 6 lines
drivers/pci/host/pcie-designware.c line 46
Quoted 2 lines
drivers/pci/host/pcie-designware.c +0
-0#define PCIE_MSI_ADDR_LO 0x820#define PCIE_MSI_ADDR_HI 0x824This seems unrelated to arm64 support, so put that in a separate patch
Yes, I will put the PCIe X8 support code in another patch.
Quoted 106 lines
Quoted 13 lines
drivers/pci/host/pcie-designware.c +3
-2@@ -68,14 +71,19 @@#define PCIE_ATU_UPPER_TARGET 0x91Cstatic 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 drivers/pci/host/pcie-designware.c line 89
Quoted 10 lines
drivers/pci/host/pcie-designware.c +5
-1+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.
Quoted 29 lines
drivers/pci/host/pcie-designware.c +21
-0@@ -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;drivers/pci/host/pcie-designware.c int __init dw_pcie_host_init(struct pcie_port *pp) · line 547
Quoted 5 lines
drivers/pci/host/pcie-designware.c +1
-0@@ -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.
Quoted 9 lines
drivers/pci/host/pcie-designware.c +1
-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;drivers/pci/host/pcie-designware.c static struct hw_pci dw_pci = { · line 797
Quoted 6 lines
drivers/pci/host/pcie-designware.c +1
-0@@ -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_setupfunction anddw_pcistructure and use the arm64 implementation.Quoted 11 lines
drivers/pci/host/pcie-designware.c +3
-0@@ -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 );drivers/pci/host/pcie-designware.c void dw_pcie_setup_rc(struct pcie_port *pp) · line 839
Quoted 8 lines
drivers/pci/host/pcie-designware.c +3
-0@@ -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.
Quoted 5 lines
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
Quoted 207 lines
drivers/pci/host/pcie-designware.c +42
-71@@ -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;drivers/pci/host/pcie-designware.h +9
-0@@ -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;.
RFC PATCH 1/3 PCI: host: designware: support ARM64
Quoted 6 lines · On Thursday 16 April 2015 13:51:47 Zhou Wang wrote:
Quoted 6 lines
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?
Quoted 6 lines
Quoted 2 lines
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
RFC PATCH 2/3 PCI: Host: Add PCIe host support for Hisilicon Soc Hip05
In reply to Zhou Wang--- 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
drivers/pci/host/Kconfig +5 -0
@@ -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
drivers/pci/host/Makefile +1 -0
@@ -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
drivers/pci/host/pcie-hisi.c new file +252 -0
252 lines not on this page · raw message
Signature · 1 line
1.9.1
RFC PATCH 3/3 Documentation: devicetree: Add hisilicon PCIe host binding
In reply to Zhou Wang--- .../devicetree/bindings/pci/hisilicon-pcie.txt | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
Documentation/devicetree/bindings/pci/hisilicon-pcie.txt new file +46 -0
@@ -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"; + };
Signature · 1 line
1.9.1
Bjorn Helgaas
maintainercover PCI: host: Add PCIe host support for Hisilicon Soc Hip05
In reply to Zhou WangQuoted 7 lines · 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
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.
Quoted 16 lines
.../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.cSignature · 6 lines
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