diff mbox

[v6,15/18] PCI: dwc: Make cpu_addr_fixup take struct dw_pcie as argument

Message ID 20171219232940.659-16-niklas.cassel@axis.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Niklas Cassel Dec. 19, 2017, 11:29 p.m. UTC
The current cpu addr fixup mask for ARTPEC-6, GENMASK(27, 0), is wrong.
The correct cpu addr fixup mask for ARTPEC-6 is GENMASK(28, 0).

However, having a hardcoded cpu addr fixup mask in each driver is
arguably wrong.
A device tree property called something like "cpu-addr-fixup-mask"
would have been a better solution.
Introducing such a property is not needed though, since we already have
pp->cfg0_base and ep->phys_base, which is derived from already existing
device tree properties.

It is also worth noting that for ARTPEC-7, hardcoding the cpu addr fixup
mask is not possible, since it uses a High Address Bits Look Up Table,
which means that it can, at runtime, map the PCIe window to an arbitrary
address in the 32-bit address space.

By using pp->cfg0_base and ep->phys_base, we avoid hardcoding a mask
in each driver. This should work for ARTPEC-6, DRA7xx, and ARTPEC-7.
I have not changed the code in DRA7xx though, since their existing
code works, but if they want, they could use the same logic as
artpec6_pcie_cpu_addr_fixup, and thus remove their hardcoded mask.

The reason why the fixup mask is needed is explained in commit f4c55c5a3f7f
("PCI: designware: Program ATU with untranslated address").

Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
---
 drivers/pci/dwc/pci-dra7xx.c      |  2 +-
 drivers/pci/dwc/pcie-artpec6.c    | 18 ++++++++++++++----
 drivers/pci/dwc/pcie-designware.c |  2 +-
 drivers/pci/dwc/pcie-designware.h |  2 +-
 4 files changed, 17 insertions(+), 7 deletions(-)

Comments

Kishon Vijay Abraham I Dec. 20, 2017, 5:52 a.m. UTC | #1
On Wednesday 20 December 2017 04:59 AM, Niklas Cassel wrote:
> The current cpu addr fixup mask for ARTPEC-6, GENMASK(27, 0), is wrong.
> The correct cpu addr fixup mask for ARTPEC-6 is GENMASK(28, 0).
> 
> However, having a hardcoded cpu addr fixup mask in each driver is
> arguably wrong.
> A device tree property called something like "cpu-addr-fixup-mask"
> would have been a better solution.
> Introducing such a property is not needed though, since we already have
> pp->cfg0_base and ep->phys_base, which is derived from already existing
> device tree properties.
> 
> It is also worth noting that for ARTPEC-7, hardcoding the cpu addr fixup
> mask is not possible, since it uses a High Address Bits Look Up Table,
> which means that it can, at runtime, map the PCIe window to an arbitrary
> address in the 32-bit address space.
> 
> By using pp->cfg0_base and ep->phys_base, we avoid hardcoding a mask
> in each driver. This should work for ARTPEC-6, DRA7xx, and ARTPEC-7.
> I have not changed the code in DRA7xx though, since their existing
> code works, but if they want, they could use the same logic as
> artpec6_pcie_cpu_addr_fixup, and thus remove their hardcoded mask.
> 
> The reason why the fixup mask is needed is explained in commit f4c55c5a3f7f
> ("PCI: designware: Program ATU with untranslated address").
> 
> Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>

Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/pci/dwc/pci-dra7xx.c      |  2 +-
>  drivers/pci/dwc/pcie-artpec6.c    | 18 ++++++++++++++----
>  drivers/pci/dwc/pcie-designware.c |  2 +-
>  drivers/pci/dwc/pcie-designware.h |  2 +-
>  4 files changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c
> index 224ff8affdce..89d87844abb3 100644
> --- a/drivers/pci/dwc/pci-dra7xx.c
> +++ b/drivers/pci/dwc/pci-dra7xx.c
> @@ -110,7 +110,7 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
>  	writel(value, pcie->base + offset);
>  }
>  
> -static u64 dra7xx_pcie_cpu_addr_fixup(u64 pci_addr)
> +static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr)
>  {
>  	return pci_addr & DRA7XX_CPU_TO_BUS_ADDR;
>  }
> diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c
> index e7de4e4649eb..318a2bd0d97e 100644
> --- a/drivers/pci/dwc/pcie-artpec6.c
> +++ b/drivers/pci/dwc/pcie-artpec6.c
> @@ -67,8 +67,6 @@ static const struct of_device_id artpec6_pcie_of_match[];
>  #define PHY_STATUS			0x118
>  #define  PHY_COSPLLLOCK			BIT(0)
>  
> -#define ARTPEC6_CPU_TO_BUS_ADDR		GENMASK(27, 0)
> -
>  static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset)
>  {
>  	u32 val;
> @@ -82,9 +80,21 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u
>  	regmap_write(artpec6_pcie->regmap, offset, val);
>  }
>  
> -static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr)
> +static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr)
>  {
> -	return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR;
> +	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
> +	struct pcie_port *pp = &pci->pp;
> +	struct dw_pcie_ep *ep = &pci->ep;
> +
> +	switch (artpec6_pcie->mode) {
> +	case DW_PCIE_RC_TYPE:
> +		return pci_addr - pp->cfg0_base;
> +	case DW_PCIE_EP_TYPE:
> +		return pci_addr - ep->phys_base;
> +	default:
> +		dev_err(pci->dev, "UNKNOWN device type\n");
> +	}
> +	return pci_addr;
>  }
>  
>  static int artpec6_pcie_establish_link(struct dw_pcie *pci)
> diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/dwc/pcie-designware.c
> index 88abdddee2ad..800be7a4f087 100644
> --- a/drivers/pci/dwc/pcie-designware.c
> +++ b/drivers/pci/dwc/pcie-designware.c
> @@ -149,7 +149,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
>  	u32 retries, val;
>  
>  	if (pci->ops->cpu_addr_fixup)
> -		cpu_addr = pci->ops->cpu_addr_fixup(cpu_addr);
> +		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
>  
>  	if (pci->iatu_unroll_enabled) {
>  		dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
> diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h
> index 24edac035160..cca5a81c1c74 100644
> --- a/drivers/pci/dwc/pcie-designware.h
> +++ b/drivers/pci/dwc/pcie-designware.h
> @@ -205,7 +205,7 @@ struct dw_pcie_ep {
>  };
>  
>  struct dw_pcie_ops {
> -	u64	(*cpu_addr_fixup)(u64 cpu_addr);
> +	u64	(*cpu_addr_fixup)(struct dw_pcie *pcie, u64 cpu_addr);
>  	u32	(*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
>  			    size_t size);
>  	void	(*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
>
diff mbox

Patch

diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c
index 224ff8affdce..89d87844abb3 100644
--- a/drivers/pci/dwc/pci-dra7xx.c
+++ b/drivers/pci/dwc/pci-dra7xx.c
@@ -110,7 +110,7 @@  static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
 	writel(value, pcie->base + offset);
 }
 
-static u64 dra7xx_pcie_cpu_addr_fixup(u64 pci_addr)
+static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr)
 {
 	return pci_addr & DRA7XX_CPU_TO_BUS_ADDR;
 }
diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c
index e7de4e4649eb..318a2bd0d97e 100644
--- a/drivers/pci/dwc/pcie-artpec6.c
+++ b/drivers/pci/dwc/pcie-artpec6.c
@@ -67,8 +67,6 @@  static const struct of_device_id artpec6_pcie_of_match[];
 #define PHY_STATUS			0x118
 #define  PHY_COSPLLLOCK			BIT(0)
 
-#define ARTPEC6_CPU_TO_BUS_ADDR		GENMASK(27, 0)
-
 static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset)
 {
 	u32 val;
@@ -82,9 +80,21 @@  static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u
 	regmap_write(artpec6_pcie->regmap, offset, val);
 }
 
-static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr)
+static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr)
 {
-	return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR;
+	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
+	struct pcie_port *pp = &pci->pp;
+	struct dw_pcie_ep *ep = &pci->ep;
+
+	switch (artpec6_pcie->mode) {
+	case DW_PCIE_RC_TYPE:
+		return pci_addr - pp->cfg0_base;
+	case DW_PCIE_EP_TYPE:
+		return pci_addr - ep->phys_base;
+	default:
+		dev_err(pci->dev, "UNKNOWN device type\n");
+	}
+	return pci_addr;
 }
 
 static int artpec6_pcie_establish_link(struct dw_pcie *pci)
diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/dwc/pcie-designware.c
index 88abdddee2ad..800be7a4f087 100644
--- a/drivers/pci/dwc/pcie-designware.c
+++ b/drivers/pci/dwc/pcie-designware.c
@@ -149,7 +149,7 @@  void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
 	u32 retries, val;
 
 	if (pci->ops->cpu_addr_fixup)
-		cpu_addr = pci->ops->cpu_addr_fixup(cpu_addr);
+		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
 
 	if (pci->iatu_unroll_enabled) {
 		dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h
index 24edac035160..cca5a81c1c74 100644
--- a/drivers/pci/dwc/pcie-designware.h
+++ b/drivers/pci/dwc/pcie-designware.h
@@ -205,7 +205,7 @@  struct dw_pcie_ep {
 };
 
 struct dw_pcie_ops {
-	u64	(*cpu_addr_fixup)(u64 cpu_addr);
+	u64	(*cpu_addr_fixup)(struct dw_pcie *pcie, u64 cpu_addr);
 	u32	(*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
 			    size_t size);
 	void	(*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,