aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2018-11-30 13:37:19 -0500
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-12-18 07:01:17 -0500
commit6d6b05e3d5337f645a411cdf72f1a083e495acb8 (patch)
tree4fd3f53736977a00b7f3110a9efd1bf8efedf6d1 /drivers/pci/controller/dwc
parent9e56f0df3684bd752347e7c3df5e8ed1fc55d139 (diff)
PCI: dwc: Don't hard-code DBI/ATU offset
The DWC PCIe core contains various separate register spaces: DBI, DBI2, ATU, DMA, etc. The relationship between the addresses of these register spaces is entirely determined by the implementation of the IP block, not by the IP block design itself. Hence, the DWC driver must not make assumptions that one register space can be accessed at a fixed offset from any other register space. To avoid such assumptions, introduce an explicit/separate register pointer for the ATU register space. In particular, the current assumption is not valid for NVIDIA's T194 SoC. The ATU register space is only used on systems that require unrolled ATU access. This property is detected at run-time for host controllers, and when this is detected, this patch provides a default value for atu_base that matches the previous assumption re: register layout. An alternative would be to update all drivers for HW that requires unrolled access to explicitly set atu_base. However, it's hard to tell which drivers would require atu_base to be set. The unrolled property is not detected for endpoint systems, and so any endpoint driver that requires unrolled access must explicitly set the iatu_unroll_enabled flag (none do at present), and so a check is added to require the driver to also set atu_base while at it. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Acked-by: Vidya Sagar <vidyas@nvidia.com>
Diffstat (limited to 'drivers/pci/controller/dwc')
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c4
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c3
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c8
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h28
4 files changed, 35 insertions, 8 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 1e7b02221eac..880210366e71 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -504,6 +504,10 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
504 dev_err(dev, "dbi_base/dbi_base2 is not populated\n"); 504 dev_err(dev, "dbi_base/dbi_base2 is not populated\n");
505 return -EINVAL; 505 return -EINVAL;
506 } 506 }
507 if (pci->iatu_unroll_enabled && !pci->atu_base) {
508 dev_err(dev, "atu_base is not populated\n");
509 return -EINVAL;
510 }
507 511
508 ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows); 512 ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);
509 if (ret < 0) { 513 if (ret < 0) {
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 29a05759a294..692dd1b264fb 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -699,6 +699,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
699 dev_dbg(pci->dev, "iATU unroll: %s\n", 699 dev_dbg(pci->dev, "iATU unroll: %s\n",
700 pci->iatu_unroll_enabled ? "enabled" : "disabled"); 700 pci->iatu_unroll_enabled ? "enabled" : "disabled");
701 701
702 if (pci->iatu_unroll_enabled && !pci->atu_base)
703 pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
704
702 dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0, 705 dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
703 PCIE_ATU_TYPE_MEM, pp->mem_base, 706 PCIE_ATU_TYPE_MEM, pp->mem_base,
704 pp->mem_bus_addr, pp->mem_size); 707 pp->mem_bus_addr, pp->mem_size);
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 2153956a0b20..93ef8c31fb39 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -93,7 +93,7 @@ static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
93{ 93{
94 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); 94 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
95 95
96 return dw_pcie_readl_dbi(pci, offset + reg); 96 return dw_pcie_readl_atu(pci, offset + reg);
97} 97}
98 98
99static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg, 99static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
@@ -101,7 +101,7 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
101{ 101{
102 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); 102 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
103 103
104 dw_pcie_writel_dbi(pci, offset + reg, val); 104 dw_pcie_writel_atu(pci, offset + reg, val);
105} 105}
106 106
107static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index, 107static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
@@ -187,7 +187,7 @@ static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
187{ 187{
188 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index); 188 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
189 189
190 return dw_pcie_readl_dbi(pci, offset + reg); 190 return dw_pcie_readl_atu(pci, offset + reg);
191} 191}
192 192
193static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg, 193static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
@@ -195,7 +195,7 @@ static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
195{ 195{
196 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index); 196 u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
197 197
198 dw_pcie_writel_dbi(pci, offset + reg, val); 198 dw_pcie_writel_atu(pci, offset + reg, val);
199} 199}
200 200
201static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index, 201static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 0989d880ac46..9943d8c68335 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -92,12 +92,20 @@
92#define PCIE_ATU_UNR_LOWER_TARGET 0x14 92#define PCIE_ATU_UNR_LOWER_TARGET 0x14
93#define PCIE_ATU_UNR_UPPER_TARGET 0x18 93#define PCIE_ATU_UNR_UPPER_TARGET 0x18
94 94
95/*
96 * The default address offset between dbi_base and atu_base. Root controller
97 * drivers are not required to initialize atu_base if the offset matches this
98 * default; the driver core automatically derives atu_base from dbi_base using
99 * this offset, if atu_base not set.
100 */
101#define DEFAULT_DBI_ATU_OFFSET (0x3 << 20)
102
95/* Register address builder */ 103/* Register address builder */
96#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \ 104#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
97 ((0x3 << 20) | ((region) << 9)) 105 ((region) << 9)
98 106
99#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ 107#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \
100 ((0x3 << 20) | ((region) << 9) | (0x1 << 8)) 108 (((region) << 9) | (0x1 << 8))
101 109
102#define MAX_MSI_IRQS 256 110#define MAX_MSI_IRQS 256
103#define MAX_MSI_IRQS_PER_CTRL 32 111#define MAX_MSI_IRQS_PER_CTRL 32
@@ -219,6 +227,8 @@ struct dw_pcie {
219 struct device *dev; 227 struct device *dev;
220 void __iomem *dbi_base; 228 void __iomem *dbi_base;
221 void __iomem *dbi_base2; 229 void __iomem *dbi_base2;
230 /* Used when iatu_unroll_enabled is true */
231 void __iomem *atu_base;
222 u32 num_viewport; 232 u32 num_viewport;
223 u8 iatu_unroll_enabled; 233 u8 iatu_unroll_enabled;
224 struct pcie_port pp; 234 struct pcie_port pp;
@@ -289,6 +299,16 @@ static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)
289 return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4); 299 return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4);
290} 300}
291 301
302static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
303{
304 __dw_pcie_write_dbi(pci, pci->atu_base, reg, 0x4, val);
305}
306
307static inline u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
308{
309 return __dw_pcie_read_dbi(pci, pci->atu_base, reg, 0x4);
310}
311
292static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci) 312static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)
293{ 313{
294 u32 reg; 314 u32 reg;