On Thu, Jan 12, 2017 at 02:28:22PM +0800, Dongdong Liu wrote: > The PCIe controller in Hip06/Hip07 SoCs is not completely > ECAM-compliant. It is non-ECAM only for the RC bus config space; for > any other bus underneath the root bus it does support ECAM access. > This is to add the almost ECAM support in DT way. > > Signed-off-by: Dongdong Liu <liudongdong3@xxxxxxxxxx> > Reviewed-by: Gabriele Paoloni <gabriele.paoloni@xxxxxxxxxx> > Reviewed-by: Zhou Wang <wangzhou1@xxxxxxxxxxxxx> Applied to pci/host-hisi for v4.11, thanks! > --- > .../devicetree/bindings/pci/hisilicon-pcie.txt | 37 +++++++++++++++ > drivers/pci/host/pcie-hisi.c | 54 ++++++++++++++++++++-- > 2 files changed, 88 insertions(+), 3 deletions(-) > > diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt > index 59c2f47..38e6dc3 100644 > --- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt > +++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt > @@ -42,3 +42,40 @@ Hip05 Example (note that Hip06 is the same except compatible): > 0x0 0 0 4 &mbigen_pcie 4 13>; > status = "ok"; > }; > + > +HiSilicon Hip06/Hip07 PCIe host bridge DT (almost ecam) description > +The properties and their meanings are identical to those described in > +host-generic-pci.txt except as listed below. > + > +Properties of the host controller node that differ from > +host-generic-pci.txt: > + > +- compatible : Must be "hisilicon,pcie-almost-ecam" > + > +- reg : Two entries: First the ECAM configuration space for any > + other bus underneath the root bus. Second, the base > + and size of the HiSilicon host bridge registers inculde > + the RC itself config space. > + > +Example: > + pcie0: pcie@a0090000 { > + compatible = "hisilicon,pcie-almost-ecam"; > + reg = <0 0xb0000000 0 0x2000000>, /* ECAM configuration space */ > + <0 0xa0090000 0 0x10000>; /* host bridge registers */ > + bus-range = <0 31>; > + msi-map = <0x0000 &its_dsa 0x0000 0x2000>; > + msi-map-mask = <0xffff>; > + #address-cells = <3>; > + #size-cells = <2>; > + device_type = "pci"; > + dma-coherent; > + ranges = <0x02000000 0 0xb2000000 0x0 0xb2000000 0 0x5ff0000 > + 0x01000000 0 0 0 0xb7ff0000 0 0x10000>; > + #interrupt-cells = <1>; > + interrupt-map-mask = <0xf800 0 0 7>; > + interrupt-map = <0x0 0 0 1 &mbigen_pcie0 650 4 > + 0x0 0 0 2 &mbigen_pcie0 650 4 > + 0x0 0 0 3 &mbigen_pcie0 650 4 > + 0x0 0 0 4 &mbigen_pcie0 650 4>; > + status = "ok"; > + }; > diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c > index a301a71..f37f5a2 100644 > --- a/drivers/pci/host/pcie-hisi.c > +++ b/drivers/pci/host/pcie-hisi.c > @@ -24,7 +24,7 @@ > #include <linux/regmap.h> > #include "../pci.h" > > -#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) > +#if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) > > static int hisi_pcie_acpi_rd_conf(struct pci_bus *bus, u32 devfn, int where, > int size, u32 *val) > @@ -74,6 +74,8 @@ static void __iomem *hisi_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, > return pci_ecam_map_bus(bus, devfn, where); > } > > +#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) > + > static int hisi_pcie_init(struct pci_config_window *cfg) > { > struct device *dev = cfg->parent; > @@ -262,17 +264,23 @@ static int hisi_pcie_probe(struct platform_device *pdev) > const struct of_device_id *match; > struct resource *reg; > struct device_driver *driver; > + struct pci_ecam_ops *ops; > int ret; > > + driver = dev->driver; > + match = of_match_device(driver->of_match_table, dev); > + if (!strcmp(match->compatible, "hisilicon,pcie-almost-ecam")) { > + ops = (struct pci_ecam_ops *)match->data; > + return pci_host_common_probe(pdev, ops); > + } > + > hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL); > if (!hisi_pcie) > return -ENOMEM; > > pp = &hisi_pcie->pp; > pp->dev = dev; > - driver = dev->driver; > > - match = of_match_device(driver->of_match_table, dev); > hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data; > > hisi_pcie->subctrl = > @@ -302,6 +310,40 @@ static int hisi_pcie_probe(struct platform_device *pdev) > &hisi_pcie_link_up_hip06 > }; > > +static int hisi_pcie_platform_init(struct pci_config_window *cfg) > +{ > + struct device *dev = cfg->parent; > + struct platform_device *pdev = to_platform_device(dev); > + struct resource *res; > + void __iomem *reg_base; > + > + if (!dev->of_node) > + return -EINVAL; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (!res) { > + dev_err(dev, "missing \"reg[1]\"property\n"); > + return -EINVAL; > + } > + > + reg_base = devm_ioremap(dev, res->start, resource_size(res)); > + if (!reg_base) > + return -ENOMEM; > + > + cfg->priv = reg_base; > + return 0; > +} > + > +struct pci_ecam_ops hisi_pcie_platform_ops = { > + .bus_shift = 20, > + .init = hisi_pcie_platform_init, > + .pci_ops = { > + .map_bus = hisi_pcie_map_bus, > + .read = hisi_pcie_acpi_rd_conf, > + .write = hisi_pcie_acpi_wr_conf, > + } > +}; > + > static const struct of_device_id hisi_pcie_of_match[] = { > { > .compatible = "hisilicon,hip05-pcie", > @@ -311,6 +353,11 @@ static int hisi_pcie_probe(struct platform_device *pdev) > .compatible = "hisilicon,hip06-pcie", > .data = (void *) &hip06_ops, > }, > + > + { > + .compatible = "hisilicon,pcie-almost-ecam", > + .data = (void *) &hisi_pcie_platform_ops, > + }, > {}, > }; > > @@ -324,3 +371,4 @@ static int hisi_pcie_probe(struct platform_device *pdev) > builtin_platform_driver(hisi_pcie_driver); > > #endif > +#endif > -- > 1.9.1 >