Skip to content

Commit 10ba085

Browse files
Prudhvi Yarlagaddakwilczynski
authored andcommitted
PCI: qcom: Disable mirroring of DBI and iATU register space in BAR region
PARF hardware block which is a wrapper on top of DWC PCIe controller mirrors the DBI and ATU register space. It uses PARF_SLV_ADDR_SPACE_SIZE register to get the size of the memory block to be mirrored and uses PARF_DBI_BASE_ADDR, PARF_ATU_BASE_ADDR registers to determine the base address of DBI and ATU space inside the memory block that is being mirrored. When a memory region which is located above the SLV_ADDR_SPACE_SIZE boundary is used for BAR region then there could be an overlap of DBI and ATU address space that is getting mirrored and the BAR region. This results in DBI and ATU address space contents getting updated when a PCIe function driver tries updating the BAR/MMIO memory region. Reference memory map of the PCIe memory region with DBI and ATU address space overlapping BAR region is as below. |---------------| | | | | ------- --------|---------------| | | |---------------| | | | DBI | | | |---------------|---->DBI_BASE_ADDR | | | | | | | | | PCIe | |---->2*SLV_ADDR_SPACE_SIZE | BAR/MMIO|---------------| | Region | ATU | | | |---------------|---->ATU_BASE_ADDR | | | | PCIe | |---------------| Memory | | DBI | Region | |---------------|---->DBI_BASE_ADDR | | | | | --------| | | | |---->SLV_ADDR_SPACE_SIZE | |---------------| | | ATU | | |---------------|---->ATU_BASE_ADDR | | | | |---------------| | | DBI | | |---------------|---->DBI_BASE_ADDR | | | | | | ----------------|---------------| | | | | | | |---------------| Currently memory region beyond the SLV_ADDR_SPACE_SIZE boundary is not used for BAR region which is why the above mentioned issue is not encountered. This issue is discovered as part of internal testing when we tried moving the BAR region beyond the SLV_ADDR_SPACE_SIZE boundary. Hence we are trying to fix this. As PARF hardware block mirrors DBI and ATU register space after every PARF_SLV_ADDR_SPACE_SIZE (default 0x1000000) boundary multiple, program maximum possible size to this register by writing 0x80000000 to it(it considers only powers of 2 as values) to avoid mirroring DBI and ATU to BAR/MMIO region. Write the physical base address of DBI and ATU register blocks to PARF_DBI_BASE_ADDR (default 0x0) and PARF_ATU_BASE_ADDR (default 0x1000) respectively to make sure DBI and ATU blocks are at expected memory locations. The register offsets PARF_DBI_BASE_ADDR_V2, PARF_SLV_ADDR_SPACE_SIZE_V2 and PARF_ATU_BASE_ADDR are applicable for platforms that use Qcom IP rev 1.9.0, 2.7.0 and 2.9.0. PARF_DBI_BASE_ADDR_V2 and PARF_SLV_ADDR_SPACE_SIZE_V2 are applicable for Qcom IP rev 2.3.3. PARF_DBI_BASE_ADDR and PARF_SLV_ADDR_SPACE_SIZE are applicable for Qcom IP rev 1.0.0, 2.3.2 and 2.4.0. Update init()/post_init() functions of the respective Qcom IP versions to program applicable PARF_DBI_BASE_ADDR, PARF_SLV_ADDR_SPACE_SIZE and PARF_ATU_BASE_ADDR register offsets. Update the SLV_ADDR_SPACE_SZ macro to 0x80000000 to set highest bit in PARF_SLV_ADDR_SPACE_SIZE register. Cache DBI and iATU physical addresses in 'struct dw_pcie' so that pcie_qcom.c driver can program these addresses in the PARF_DBI_BASE_ADDR and PARF_ATU_BASE_ADDR registers. Suggested-by: Manivannan Sadhasivam <[email protected]> Link: https://lore.kernel.org/linux-pci/[email protected] Signed-off-by: Prudhvi Yarlagadda <[email protected]> Signed-off-by: Krzysztof Wilczyński <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Reviewed-by: Mayank Rana <[email protected]>
1 parent 4581403 commit 10ba085

File tree

3 files changed

+61
-15
lines changed

3 files changed

+61
-15
lines changed

drivers/pci/controller/dwc/pcie-designware.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
112112
pci->dbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
113113
if (IS_ERR(pci->dbi_base))
114114
return PTR_ERR(pci->dbi_base);
115+
pci->dbi_phys_addr = res->start;
115116
}
116117

117118
/* DBI2 is mainly useful for the endpoint controller */
@@ -134,6 +135,7 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
134135
pci->atu_base = devm_ioremap_resource(pci->dev, res);
135136
if (IS_ERR(pci->atu_base))
136137
return PTR_ERR(pci->atu_base);
138+
pci->atu_phys_addr = res->start;
137139
} else {
138140
pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
139141
}

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,10 @@ struct dw_pcie_ops {
407407
struct dw_pcie {
408408
struct device *dev;
409409
void __iomem *dbi_base;
410+
resource_size_t dbi_phys_addr;
410411
void __iomem *dbi_base2;
411412
void __iomem *atu_base;
413+
resource_size_t atu_phys_addr;
412414
size_t atu_size;
413415
u32 num_ib_windows;
414416
u32 num_ob_windows;

drivers/pci/controller/dwc/pcie-qcom.c

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#define PARF_PHY_REFCLK 0x4c
4646
#define PARF_CONFIG_BITS 0x50
4747
#define PARF_DBI_BASE_ADDR 0x168
48+
#define PARF_SLV_ADDR_SPACE_SIZE 0x16c
4849
#define PARF_MHI_CLOCK_RESET_CTRL 0x174
4950
#define PARF_AXI_MSTR_WR_ADDR_HALT 0x178
5051
#define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8
@@ -55,8 +56,13 @@
5556
#define PARF_INT_ALL_MASK 0x22c
5657
#define PARF_SID_OFFSET 0x234
5758
#define PARF_BDF_TRANSLATE_CFG 0x24c
58-
#define PARF_SLV_ADDR_SPACE_SIZE 0x358
59+
#define PARF_DBI_BASE_ADDR_V2 0x350
60+
#define PARF_DBI_BASE_ADDR_V2_HI 0x354
61+
#define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358
62+
#define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c
5963
#define PARF_NO_SNOOP_OVERIDE 0x3d4
64+
#define PARF_ATU_BASE_ADDR 0x634
65+
#define PARF_ATU_BASE_ADDR_HI 0x638
6066
#define PARF_DEVICE_TYPE 0x1000
6167
#define PARF_BDF_TO_SID_TABLE_N 0x2000
6268
#define PARF_BDF_TO_SID_CFG 0x2c00
@@ -111,7 +117,7 @@
111117
#define PHY_RX0_EQ(x) FIELD_PREP(GENMASK(26, 24), x)
112118

113119
/* PARF_SLV_ADDR_SPACE_SIZE register value */
114-
#define SLV_ADDR_SPACE_SZ 0x10000000
120+
#define SLV_ADDR_SPACE_SZ 0x80000000
115121

116122
/* PARF_MHI_CLOCK_RESET_CTRL register fields */
117123
#define AHB_CLK_EN BIT(0)
@@ -330,6 +336,50 @@ static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
330336
dw_pcie_dbi_ro_wr_dis(pci);
331337
}
332338

339+
static void qcom_pcie_configure_dbi_base(struct qcom_pcie *pcie)
340+
{
341+
struct dw_pcie *pci = pcie->pci;
342+
343+
if (pci->dbi_phys_addr) {
344+
/*
345+
* PARF_DBI_BASE_ADDR register is in CPU domain and require to
346+
* be programmed with CPU physical address.
347+
*/
348+
writel(lower_32_bits(pci->dbi_phys_addr), pcie->parf +
349+
PARF_DBI_BASE_ADDR);
350+
writel(SLV_ADDR_SPACE_SZ, pcie->parf +
351+
PARF_SLV_ADDR_SPACE_SIZE);
352+
}
353+
}
354+
355+
static void qcom_pcie_configure_dbi_atu_base(struct qcom_pcie *pcie)
356+
{
357+
struct dw_pcie *pci = pcie->pci;
358+
359+
if (pci->dbi_phys_addr) {
360+
/*
361+
* PARF_DBI_BASE_ADDR_V2 and PARF_ATU_BASE_ADDR registers are
362+
* in CPU domain and require to be programmed with CPU
363+
* physical addresses.
364+
*/
365+
writel(lower_32_bits(pci->dbi_phys_addr), pcie->parf +
366+
PARF_DBI_BASE_ADDR_V2);
367+
writel(upper_32_bits(pci->dbi_phys_addr), pcie->parf +
368+
PARF_DBI_BASE_ADDR_V2_HI);
369+
370+
if (pci->atu_phys_addr) {
371+
writel(lower_32_bits(pci->atu_phys_addr), pcie->parf +
372+
PARF_ATU_BASE_ADDR);
373+
writel(upper_32_bits(pci->atu_phys_addr), pcie->parf +
374+
PARF_ATU_BASE_ADDR_HI);
375+
}
376+
377+
writel(0x0, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_V2);
378+
writel(SLV_ADDR_SPACE_SZ, pcie->parf +
379+
PARF_SLV_ADDR_SPACE_SIZE_V2_HI);
380+
}
381+
}
382+
333383
static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie)
334384
{
335385
u32 val;
@@ -546,8 +596,7 @@ static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie)
546596

547597
static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
548598
{
549-
/* change DBI base address */
550-
writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
599+
qcom_pcie_configure_dbi_base(pcie);
551600

552601
if (IS_ENABLED(CONFIG_PCI_MSI)) {
553602
u32 val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT);
@@ -634,8 +683,7 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
634683
val &= ~PHY_TEST_PWR_DOWN;
635684
writel(val, pcie->parf + PARF_PHY_CTRL);
636685

637-
/* change DBI base address */
638-
writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
686+
qcom_pcie_configure_dbi_base(pcie);
639687

640688
/* MAC PHY_POWERDOWN MUX DISABLE */
641689
val = readl(pcie->parf + PARF_SYS_CTRL);
@@ -817,13 +865,11 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
817865
u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
818866
u32 val;
819867

820-
writel(SLV_ADDR_SPACE_SZ, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE);
821-
822868
val = readl(pcie->parf + PARF_PHY_CTRL);
823869
val &= ~PHY_TEST_PWR_DOWN;
824870
writel(val, pcie->parf + PARF_PHY_CTRL);
825871

826-
writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
872+
qcom_pcie_configure_dbi_atu_base(pcie);
827873

828874
writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS
829875
| SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS |
@@ -919,8 +965,7 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
919965
val &= ~PHY_TEST_PWR_DOWN;
920966
writel(val, pcie->parf + PARF_PHY_CTRL);
921967

922-
/* change DBI base address */
923-
writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
968+
qcom_pcie_configure_dbi_atu_base(pcie);
924969

925970
/* MAC PHY_POWERDOWN MUX DISABLE */
926971
val = readl(pcie->parf + PARF_SYS_CTRL);
@@ -1129,14 +1174,11 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
11291174
u32 val;
11301175
int i;
11311176

1132-
writel(SLV_ADDR_SPACE_SZ,
1133-
pcie->parf + PARF_SLV_ADDR_SPACE_SIZE);
1134-
11351177
val = readl(pcie->parf + PARF_PHY_CTRL);
11361178
val &= ~PHY_TEST_PWR_DOWN;
11371179
writel(val, pcie->parf + PARF_PHY_CTRL);
11381180

1139-
writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
1181+
qcom_pcie_configure_dbi_atu_base(pcie);
11401182

11411183
writel(DEVICE_TYPE_RC, pcie->parf + PARF_DEVICE_TYPE);
11421184
writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN,

0 commit comments

Comments
 (0)