|
52 | 52 | #define PCIE20_PARF_DBI_BASE_ADDR 0x168
|
53 | 53 | #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C
|
54 | 54 | #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 | + |
55 | 59 | #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178
|
56 | 60 | #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1A8
|
57 | 61 | #define PCIE20_PARF_LTSSM 0x1B0
|
@@ -179,13 +183,19 @@ struct qcom_pcie_resources_2_7_0 {
|
179 | 183 | struct reset_control *pci_reset;
|
180 | 184 | };
|
181 | 185 |
|
| 186 | +struct qcom_pcie_resources_2_9_0 { |
| 187 | + struct clk_bulk_data clks[5]; |
| 188 | + struct reset_control *rst; |
| 189 | +}; |
| 190 | + |
182 | 191 | union qcom_pcie_resources {
|
183 | 192 | struct qcom_pcie_resources_1_0_0 v1_0_0;
|
184 | 193 | struct qcom_pcie_resources_2_1_0 v2_1_0;
|
185 | 194 | struct qcom_pcie_resources_2_3_2 v2_3_2;
|
186 | 195 | struct qcom_pcie_resources_2_3_3 v2_3_3;
|
187 | 196 | struct qcom_pcie_resources_2_4_0 v2_4_0;
|
188 | 197 | struct qcom_pcie_resources_2_7_0 v2_7_0;
|
| 198 | + struct qcom_pcie_resources_2_9_0 v2_9_0; |
189 | 199 | };
|
190 | 200 |
|
191 | 201 | struct qcom_pcie;
|
@@ -1279,6 +1289,112 @@ static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
|
1279 | 1289 | regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
|
1280 | 1290 | }
|
1281 | 1291 |
|
| 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 | + |
1282 | 1398 | static int qcom_pcie_link_up(struct dw_pcie *pci)
|
1283 | 1399 | {
|
1284 | 1400 | 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 = {
|
1468 | 1584 | .config_sid = qcom_pcie_config_sid_sm8250,
|
1469 | 1585 | };
|
1470 | 1586 |
|
| 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 | + |
1471 | 1596 | static const struct qcom_pcie_cfg apq8084_cfg = {
|
1472 | 1597 | .ops = &ops_1_0_0,
|
1473 | 1598 | };
|
@@ -1529,6 +1654,10 @@ static const struct qcom_pcie_cfg sc8180x_cfg = {
|
1529 | 1654 | .has_tbu_clk = true,
|
1530 | 1655 | };
|
1531 | 1656 |
|
| 1657 | +static const struct qcom_pcie_cfg ipq6018_cfg = { |
| 1658 | + .ops = &ops_2_9_0, |
| 1659 | +}; |
| 1660 | + |
1532 | 1661 | static const struct dw_pcie_ops dw_pcie_ops = {
|
1533 | 1662 | .link_up = qcom_pcie_link_up,
|
1534 | 1663 | .start_link = qcom_pcie_start_link,
|
@@ -1639,6 +1768,7 @@ static const struct of_device_id qcom_pcie_match[] = {
|
1639 | 1768 | { .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
|
1640 | 1769 | { .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
|
1641 | 1770 | { .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
|
| 1771 | + { .compatible = "qcom,pcie-ipq6018", .data = &ipq6018_cfg }, |
1642 | 1772 | { }
|
1643 | 1773 | };
|
1644 | 1774 |
|
|
0 commit comments