Skip to content

Commit 4660e50

Browse files
PCI: qcom: Prepare for the DWC ECAM enablement
To support the DWC ECAM mechanism, prepare the driver by performing below configurations: 1. Since the ELBI region will be covered by the ECAM 'config' space, override the 'elbi_base' with the address derived from 'dbi_base' and the offset from PARF_SLV_DBI_ELBI register. 2. Block the transactions from the host bridge to devices other than Root Port on the root bus to return all F's. This is required when the 'CFG Shift Feature' of iATU is enabled. Signed-off-by: Krishna Chaitanya Chundru <[email protected]> [mani: code split, reworded subject/description and comments] Signed-off-by: Manivannan Sadhasivam <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent f6fd357 commit 4660e50

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8
5656
#define PARF_Q2A_FLUSH 0x1ac
5757
#define PARF_LTSSM 0x1b0
58+
#define PARF_SLV_DBI_ELBI 0x1b4
5859
#define PARF_INT_ALL_STATUS 0x224
5960
#define PARF_INT_ALL_CLEAR 0x228
6061
#define PARF_INT_ALL_MASK 0x22c
@@ -64,6 +65,16 @@
6465
#define PARF_DBI_BASE_ADDR_V2_HI 0x354
6566
#define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358
6667
#define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c
68+
#define PARF_BLOCK_SLV_AXI_WR_BASE 0x360
69+
#define PARF_BLOCK_SLV_AXI_WR_BASE_HI 0x364
70+
#define PARF_BLOCK_SLV_AXI_WR_LIMIT 0x368
71+
#define PARF_BLOCK_SLV_AXI_WR_LIMIT_HI 0x36c
72+
#define PARF_BLOCK_SLV_AXI_RD_BASE 0x370
73+
#define PARF_BLOCK_SLV_AXI_RD_BASE_HI 0x374
74+
#define PARF_BLOCK_SLV_AXI_RD_LIMIT 0x378
75+
#define PARF_BLOCK_SLV_AXI_RD_LIMIT_HI 0x37c
76+
#define PARF_ECAM_BASE 0x380
77+
#define PARF_ECAM_BASE_HI 0x384
6778
#define PARF_NO_SNOOP_OVERRIDE 0x3d4
6879
#define PARF_ATU_BASE_ADDR 0x634
6980
#define PARF_ATU_BASE_ADDR_HI 0x638
@@ -87,6 +98,7 @@
8798

8899
/* PARF_SYS_CTRL register fields */
89100
#define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29)
101+
#define PCIE_ECAM_BLOCKER_EN BIT(26)
90102
#define MST_WAKEUP_EN BIT(13)
91103
#define SLV_WAKEUP_EN BIT(12)
92104
#define MSTR_ACLK_CGC_DIS BIT(10)
@@ -134,6 +146,9 @@
134146
/* PARF_LTSSM register fields */
135147
#define LTSSM_EN BIT(8)
136148

149+
/* PARF_SLV_DBI_ELBI */
150+
#define SLV_DBI_ELBI_ADDR_BASE GENMASK(11, 0)
151+
137152
/* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */
138153
#define PARF_INT_ALL_LINK_UP BIT(13)
139154
#define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23)
@@ -312,6 +327,47 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
312327
qcom_perst_assert(pcie, false);
313328
}
314329

330+
static void qcom_pci_config_ecam(struct dw_pcie_rp *pp)
331+
{
332+
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
333+
struct qcom_pcie *pcie = to_qcom_pcie(pci);
334+
u64 addr, addr_end;
335+
u32 val;
336+
337+
writel_relaxed(lower_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE);
338+
writel_relaxed(upper_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE_HI);
339+
340+
/*
341+
* The only device on the root bus is a single Root Port. If we try to
342+
* access any devices other than Device/Function 00.0 on Bus 0, the TLP
343+
* will go outside of the controller to the PCI bus. But with CFG Shift
344+
* Feature (ECAM) enabled in iATU, there is no guarantee that the
345+
* response is going to be all F's. Hence, to make sure that the
346+
* requester gets all F's response for accesses other than the Root
347+
* Port, configure iATU to block the transactions starting from
348+
* function 1 of the root bus to the end of the root bus (i.e., from
349+
* dbi_base + 4KB to dbi_base + 1MB).
350+
*/
351+
addr = pci->dbi_phys_addr + SZ_4K;
352+
writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE);
353+
writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE_HI);
354+
355+
writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE);
356+
writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE_HI);
357+
358+
addr_end = pci->dbi_phys_addr + SZ_1M - 1;
359+
360+
writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT);
361+
writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT_HI);
362+
363+
writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT);
364+
writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT_HI);
365+
366+
val = readl_relaxed(pcie->parf + PARF_SYS_CTRL);
367+
val |= PCIE_ECAM_BLOCKER_EN;
368+
writel_relaxed(val, pcie->parf + PARF_SYS_CTRL);
369+
}
370+
315371
static int qcom_pcie_start_link(struct dw_pcie *pci)
316372
{
317373
struct qcom_pcie *pcie = to_qcom_pcie(pci);
@@ -1284,6 +1340,7 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
12841340
{
12851341
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
12861342
struct qcom_pcie *pcie = to_qcom_pcie(pci);
1343+
u16 offset;
12871344
int ret;
12881345

12891346
qcom_ep_reset_assert(pcie);
@@ -1292,6 +1349,17 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
12921349
if (ret)
12931350
return ret;
12941351

1352+
if (pp->ecam_enabled) {
1353+
/*
1354+
* Override ELBI when ECAM is enabled, as when ECAM is enabled,
1355+
* ELBI moves under the 'config' space.
1356+
*/
1357+
offset = FIELD_GET(SLV_DBI_ELBI_ADDR_BASE, readl(pcie->parf + PARF_SLV_DBI_ELBI));
1358+
pci->elbi_base = pci->dbi_base + offset;
1359+
1360+
qcom_pci_config_ecam(pp);
1361+
}
1362+
12951363
ret = qcom_pcie_phy_power_on(pcie);
12961364
if (ret)
12971365
goto err_deinit;

0 commit comments

Comments
 (0)