Re: [PATCH V4 1/2] PCI: hisi: Add ECAM support for devices that are not RC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[+cc Jingoo]

On Wed, Nov 09, 2016 at 05:14:56PM +0800, Dongdong Liu wrote:
> This patch modifies the current Hip05/Hip06 PCIe host
> controller driver to add support for 'almost ECAM'
> compliant platforms. Some controllers are ECAM compliant
> for all the devices of the hierarchy except the root
> complex; this patch adds support for such controllers.
> 
> This is needed in preparation for the ACPI based driver
> to allow both DT and ACPI drivers to use the same BIOS
> (that configure the Designware iATUs).
> This commit doesn't break backward compatibility with
> previous non-ECAM platforms.
> 
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@xxxxxxxxxx>
> Signed-off-by: Dongdong Liu <liudongdong3@xxxxxxxxxx>
> ---
>  .../devicetree/bindings/pci/hisilicon-pcie.txt     | 15 +++++---
>  drivers/pci/host/Kconfig                           |  4 +-
>  drivers/pci/host/pcie-designware.c                 |  4 +-
>  drivers/pci/host/pcie-designware.h                 |  2 +
>  drivers/pci/host/pcie-hisi.c                       | 45 ++++++++++++++++++++++
>  5 files changed, 60 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> index 59c2f47..87a597a 100644
> --- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> @@ -9,10 +9,13 @@ Additional properties are described here:
>  
>  Required properties
>  - compatible: Should contain "hisilicon,hip05-pcie" or "hisilicon,hip06-pcie".
> -- reg: Should contain rc_dbi, config registers location and length.
> -- reg-names: Must include the following entries:
> +- reg: Should contain rc_dbi and  either config or ecam-cfg registers
> +       location and length (it depends on the platform BIOS).
> +- reg-names: Must include
>    "rc_dbi": controller configuration registers;
> -  "config": PCIe configuration space registers.
> +  and one of the following entries:
> +    "config": PCIe configuration space registers for non-ECAM platforms.
> +    "ecam-cfg": PCIe configuration space registers for ECAM platforms
>  - msi-parent: Should be its_pcie which is an ITS receiving MSI interrupts.
>  - port-id: Should be 0, 1, 2 or 3.
>  
> @@ -23,8 +26,10 @@ Optional properties:
>  Hip05 Example (note that Hip06 is the same except compatible):
>  	pcie@0xb0080000 {
>  		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
> -		reg = <0 0xb0080000 0 0x10000>, <0x220 0x00000000 0 0x2000>;
> -		reg-names = "rc_dbi", "config";
> +		reg = <0 0xb0080000 0 0x10000>,
> +		      <0x220 0x00000000 0 0x2000>
> +		/* or <0x220 0x00100000 0 0x0f00000> for ecam-cfg*/;

Add space before closing "*/".

> +		reg-names = "rc_dbi", "config" /* or "ecam-cfg" */;
>  		bus-range = <0  15>;
>  		msi-parent = <&its_pcie>;
>  		#address-cells = <3>;
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index d7e7c0a..ae98644 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -219,13 +219,13 @@ config PCIE_ALTERA_MSI
>  
>  config PCI_HISI
>  	depends on OF && ARM64
> -	bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
> +	bool "HiSilicon Hip05 and Hip06 and Hip07 SoCs PCIe controllers"
>  	depends on PCI_MSI_IRQ_DOMAIN
>  	select PCIEPORTBUS
>  	select PCIE_DW
>  	help
>  	  Say Y here if you want PCIe controller support on HiSilicon
> -	  Hip05 and Hip06 SoCs
> +	  Hip05 and Hip06 and Hip07 SoCs
>  
>  config PCIE_QCOM
>  	bool "Qualcomm PCIe controller"
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 035f50c..da11644 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -101,8 +101,6 @@
>  #define PCIE_PHY_DEBUG_R1_LINK_UP	(0x1 << 4)
>  #define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING	(0x1 << 29)
>  
> -static struct pci_ops dw_pcie_ops;
> -
>  int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
>  {
>  	if ((uintptr_t)addr & (size - 1)) {
> @@ -800,7 +798,7 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  	return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val);
>  }
>  
> -static struct pci_ops dw_pcie_ops = {
> +struct pci_ops dw_pcie_ops = {
>  	.read = dw_pcie_rd_conf,
>  	.write = dw_pcie_wr_conf,
>  };
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index a567ea2..30d228a 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -83,4 +83,6 @@ struct pcie_host_ops {
>  void dw_pcie_setup_rc(struct pcie_port *pp);
>  int dw_pcie_host_init(struct pcie_port *pp);
>  
> +extern struct pci_ops dw_pcie_ops;
> +
>  #endif /* _PCIE_DESIGNWARE_H */
> diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
> index 56154c2..555c964 100644
> --- a/drivers/pci/host/pcie-hisi.c
> +++ b/drivers/pci/host/pcie-hisi.c
> @@ -43,6 +43,34 @@ struct hisi_pcie {
>  	struct pcie_soc_ops *soc_ops;
>  };
>  
> +static inline int hisi_rd_ecam_conf(struct pcie_port *pp, struct pci_bus *bus,
> +				    unsigned int devfn, int where, int size,
> +				    u32 *value)
> +{
> +	return pci_generic_config_read(bus, devfn, where, size, value);
> +}
> +
> +static inline int hisi_wr_ecam_conf(struct pcie_port *pp, struct pci_bus *bus,
> +				    unsigned int devfn, int where, int size,
> +				    u32 value)
> +{
> +	return pci_generic_config_write(bus, devfn, where, size, value);
> +}
> +
> +static void __iomem *hisi_pci_map_cfg_bus_cam(struct pci_bus *bus,
> +					      unsigned int devfn,
> +					      int where)
> +{
> +	void __iomem *addr;
> +	struct pcie_port *pp = bus->sysdata;
> +
> +	addr = pp->va_cfg1_base - (pp->busn->start << 20) +
> +		((bus->number << 20) | (devfn << 12)) +
> +		where;
> +
> +	return addr;
> +}
> +
>  /* HipXX PCIe host only supports 32-bit config access */
>  static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
>  			      u32 *val)
> @@ -190,6 +218,23 @@ static int hisi_pcie_probe(struct platform_device *pdev)
>  		return PTR_ERR(pp->dbi_base);
>  	}
>  
> +	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam-cfg");
> +	if (reg) {
> +		/* ECAM driver version */
> +		hisi_pcie->pp.va_cfg0_base =
> +		devm_ioremap_resource(&pdev->dev, reg);
> +		if (IS_ERR(hisi_pcie->pp.va_cfg0_base)) {
> +			dev_err(pp->dev, "cannot get ecam-cfg\n");
> +			return PTR_ERR(hisi_pcie->pp.va_cfg0_base);
> +		}
> +		hisi_pcie->pp.va_cfg1_base = hisi_pcie->pp.va_cfg0_base;
> +
> +		dw_pcie_ops.map_bus = hisi_pci_map_cfg_bus_cam;

I don't really like this part.  We're scribbling on dw_pcie_ops, which this
driver does not own.  That breaks the encapsulation and means that using
two different DW-based drivers in the same system (admittedly unlikely)
would fail mysteriously.

I wonder if this could be solved by allowing the DW-based drivers to supply
their own pci_ops.  If we did that, it might let us get rid of the
rd_own_conf, wr_own_conf, rd_other_conf, and wr_other_conf function
pointers.  I haven't worked through it, but it's possible the result would
be easier to read.

It's also possible it would be a lot of code churn for no real gain, and
breaking the encapsulation makes the most sense.  What do you think?

> +
> +		hisi_pcie_host_ops.rd_other_conf = hisi_rd_ecam_conf;
> +		hisi_pcie_host_ops.wr_other_conf = hisi_wr_ecam_conf;
> +	}
> +
>  	ret = hisi_add_pcie_port(hisi_pcie, pdev);
>  	if (ret)
>  		return ret;
> -- 
> 1.9.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux