Skip to content

Commit 0cf7c2e

Browse files
Selvam Sathappan Periakaruppanbjorn-helgaas
authored andcommitted
PCI: qcom: Add IPQ60xx support
IPQ60xx series of SoCs have one port of PCIe gen 3. Add support for that platform. The code is based on downstream[1] Codeaurora kernel v5.4 (branch win.linuxopenwrt.2.0). Split out the DBI registers access part from .init into .post_init. DBI registers are only accessible after phy_power_on(). [1] https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-ipq-5.4/ Link: https://lore.kernel.org/r/f7f848653c99abbf9a0f877949a44e52329543ae.1655799816.git.baruch@tkos.co.il Tested-by: Robert Marko <[email protected]> Signed-off-by: Selvam Sathappan Periakaruppan <[email protected]> Signed-off-by: Baruch Siach <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Rob Herring <[email protected]> Reviewed-by: Johan Hovold <[email protected]> Acked-by: Stanimir Varbanov <[email protected]>
1 parent 9a76580 commit 0cf7c2e

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676

7777
#define GEN3_RELATED_OFF 0x890
7878
#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0)
79+
#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13)
7980
#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16)
8081
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24
8182
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24)

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

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
#define PCIE20_PARF_DBI_BASE_ADDR 0x168
5353
#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C
5454
#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174
55+
#define AHB_CLK_EN BIT(0)
56+
#define MSTR_AXI_CLK_EN BIT(1)
57+
#define BYPASS BIT(4)
58+
5559
#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178
5660
#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1A8
5761
#define PCIE20_PARF_LTSSM 0x1B0
@@ -179,13 +183,19 @@ struct qcom_pcie_resources_2_7_0 {
179183
struct reset_control *pci_reset;
180184
};
181185

186+
struct qcom_pcie_resources_2_9_0 {
187+
struct clk_bulk_data clks[5];
188+
struct reset_control *rst;
189+
};
190+
182191
union qcom_pcie_resources {
183192
struct qcom_pcie_resources_1_0_0 v1_0_0;
184193
struct qcom_pcie_resources_2_1_0 v2_1_0;
185194
struct qcom_pcie_resources_2_3_2 v2_3_2;
186195
struct qcom_pcie_resources_2_3_3 v2_3_3;
187196
struct qcom_pcie_resources_2_4_0 v2_4_0;
188197
struct qcom_pcie_resources_2_7_0 v2_7_0;
198+
struct qcom_pcie_resources_2_9_0 v2_9_0;
189199
};
190200

191201
struct qcom_pcie;
@@ -1279,6 +1289,112 @@ static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
12791289
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
12801290
}
12811291

1292+
static int qcom_pcie_get_resources_2_9_0(struct qcom_pcie *pcie)
1293+
{
1294+
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
1295+
struct dw_pcie *pci = pcie->pci;
1296+
struct device *dev = pci->dev;
1297+
int ret;
1298+
1299+
res->clks[0].id = "iface";
1300+
res->clks[1].id = "axi_m";
1301+
res->clks[2].id = "axi_s";
1302+
res->clks[3].id = "axi_bridge";
1303+
res->clks[4].id = "rchng";
1304+
1305+
ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks);
1306+
if (ret < 0)
1307+
return ret;
1308+
1309+
res->rst = devm_reset_control_array_get_exclusive(dev);
1310+
if (IS_ERR(res->rst))
1311+
return PTR_ERR(res->rst);
1312+
1313+
return 0;
1314+
}
1315+
1316+
static void qcom_pcie_deinit_2_9_0(struct qcom_pcie *pcie)
1317+
{
1318+
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
1319+
1320+
clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
1321+
}
1322+
1323+
static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie)
1324+
{
1325+
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
1326+
struct device *dev = pcie->pci->dev;
1327+
int ret;
1328+
1329+
ret = reset_control_assert(res->rst);
1330+
if (ret) {
1331+
dev_err(dev, "reset assert failed (%d)\n", ret);
1332+
return ret;
1333+
}
1334+
1335+
/*
1336+
* Delay periods before and after reset deassert are working values
1337+
* from downstream Codeaurora kernel
1338+
*/
1339+
usleep_range(2000, 2500);
1340+
1341+
ret = reset_control_deassert(res->rst);
1342+
if (ret) {
1343+
dev_err(dev, "reset deassert failed (%d)\n", ret);
1344+
return ret;
1345+
}
1346+
1347+
usleep_range(2000, 2500);
1348+
1349+
return clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
1350+
}
1351+
1352+
static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
1353+
{
1354+
struct dw_pcie *pci = pcie->pci;
1355+
u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
1356+
u32 val;
1357+
int i;
1358+
1359+
writel(SLV_ADDR_SPACE_SZ,
1360+
pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE);
1361+
1362+
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
1363+
val &= ~BIT(0);
1364+
writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
1365+
1366+
writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
1367+
1368+
writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE);
1369+
writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN,
1370+
pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
1371+
writel(GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS |
1372+
GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL,
1373+
pci->dbi_base + GEN3_RELATED_OFF);
1374+
1375+
writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS |
1376+
SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS |
1377+
AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS,
1378+
pcie->parf + PCIE20_PARF_SYS_CTRL);
1379+
1380+
writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH);
1381+
1382+
dw_pcie_dbi_ro_wr_en(pci);
1383+
writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP);
1384+
1385+
val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
1386+
val &= ~PCI_EXP_LNKCAP_ASPMS;
1387+
writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP);
1388+
1389+
writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset +
1390+
PCI_EXP_DEVCTL2);
1391+
1392+
for (i = 0; i < 256; i++)
1393+
writel(0, pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N + (4 * i));
1394+
1395+
return 0;
1396+
}
1397+
12821398
static int qcom_pcie_link_up(struct dw_pcie *pci)
12831399
{
12841400
u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
@@ -1468,6 +1584,15 @@ static const struct qcom_pcie_ops ops_1_9_0 = {
14681584
.config_sid = qcom_pcie_config_sid_sm8250,
14691585
};
14701586

1587+
/* Qcom IP rev.: 2.9.0 Synopsys IP rev.: 5.00a */
1588+
static const struct qcom_pcie_ops ops_2_9_0 = {
1589+
.get_resources = qcom_pcie_get_resources_2_9_0,
1590+
.init = qcom_pcie_init_2_9_0,
1591+
.post_init = qcom_pcie_post_init_2_9_0,
1592+
.deinit = qcom_pcie_deinit_2_9_0,
1593+
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
1594+
};
1595+
14711596
static const struct qcom_pcie_cfg apq8084_cfg = {
14721597
.ops = &ops_1_0_0,
14731598
};
@@ -1529,6 +1654,10 @@ static const struct qcom_pcie_cfg sc8180x_cfg = {
15291654
.has_tbu_clk = true,
15301655
};
15311656

1657+
static const struct qcom_pcie_cfg ipq6018_cfg = {
1658+
.ops = &ops_2_9_0,
1659+
};
1660+
15321661
static const struct dw_pcie_ops dw_pcie_ops = {
15331662
.link_up = qcom_pcie_link_up,
15341663
.start_link = qcom_pcie_start_link,
@@ -1639,6 +1768,7 @@ static const struct of_device_id qcom_pcie_match[] = {
16391768
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
16401769
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
16411770
{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
1771+
{ .compatible = "qcom,pcie-ipq6018", .data = &ipq6018_cfg },
16421772
{ }
16431773
};
16441774

0 commit comments

Comments
 (0)