Skip to content

Commit c4860af

Browse files
jhovoldLorenzo Pieralisi
authored andcommitted
PCI: qcom: Add basic interconnect support
On Qualcomm platforms like SC8280XP and SA8540P, interconnect bandwidth must be requested before enabling interconnect clocks. Add basic support for managing an optional "pcie-mem" interconnect path by setting a low constraint before enabling clocks and updating it after the link is up. Note that it is not possible for a controller driver to set anything but a maximum peak bandwidth as expected average bandwidth will vary with use case and actual use (and power policy?). This very much remains an unresolved problem with the interconnect framework. Also note that no constraint is set for the SC8280XP/SA8540P "cpu-pcie" path for now as it is not clear what an appropriate constraint would be (and the system does not crash when left unspecified). Link: https://lore.kernel.org/r/[email protected] Fixes: 7057451 ("PCI: qcom: Add support for SC8280XP") Signed-off-by: Johan Hovold <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Reviewed-by: Brian Masney <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Acked-by: Georgi Djakov <[email protected]>
1 parent 3a936b2 commit c4860af

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/crc8.h>
1313
#include <linux/delay.h>
1414
#include <linux/gpio/consumer.h>
15+
#include <linux/interconnect.h>
1516
#include <linux/interrupt.h>
1617
#include <linux/io.h>
1718
#include <linux/iopoll.h>
@@ -223,6 +224,7 @@ struct qcom_pcie {
223224
union qcom_pcie_resources res;
224225
struct phy *phy;
225226
struct gpio_desc *reset;
227+
struct icc_path *icc_mem;
226228
const struct qcom_pcie_cfg *cfg;
227229
};
228230

@@ -1639,6 +1641,74 @@ static const struct dw_pcie_ops dw_pcie_ops = {
16391641
.start_link = qcom_pcie_start_link,
16401642
};
16411643

1644+
static int qcom_pcie_icc_init(struct qcom_pcie *pcie)
1645+
{
1646+
struct dw_pcie *pci = pcie->pci;
1647+
int ret;
1648+
1649+
pcie->icc_mem = devm_of_icc_get(pci->dev, "pcie-mem");
1650+
if (IS_ERR(pcie->icc_mem))
1651+
return PTR_ERR(pcie->icc_mem);
1652+
1653+
/*
1654+
* Some Qualcomm platforms require interconnect bandwidth constraints
1655+
* to be set before enabling interconnect clocks.
1656+
*
1657+
* Set an initial peak bandwidth corresponding to single-lane Gen 1
1658+
* for the pcie-mem path.
1659+
*/
1660+
ret = icc_set_bw(pcie->icc_mem, 0, MBps_to_icc(250));
1661+
if (ret) {
1662+
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
1663+
ret);
1664+
return ret;
1665+
}
1666+
1667+
return 0;
1668+
}
1669+
1670+
static void qcom_pcie_icc_update(struct qcom_pcie *pcie)
1671+
{
1672+
struct dw_pcie *pci = pcie->pci;
1673+
u32 offset, status, bw;
1674+
int speed, width;
1675+
int ret;
1676+
1677+
if (!pcie->icc_mem)
1678+
return;
1679+
1680+
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
1681+
status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
1682+
1683+
/* Only update constraints if link is up. */
1684+
if (!(status & PCI_EXP_LNKSTA_DLLLA))
1685+
return;
1686+
1687+
speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, status);
1688+
width = FIELD_GET(PCI_EXP_LNKSTA_NLW, status);
1689+
1690+
switch (speed) {
1691+
case 1:
1692+
bw = MBps_to_icc(250);
1693+
break;
1694+
case 2:
1695+
bw = MBps_to_icc(500);
1696+
break;
1697+
default:
1698+
WARN_ON_ONCE(1);
1699+
fallthrough;
1700+
case 3:
1701+
bw = MBps_to_icc(985);
1702+
break;
1703+
}
1704+
1705+
ret = icc_set_bw(pcie->icc_mem, 0, width * bw);
1706+
if (ret) {
1707+
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
1708+
ret);
1709+
}
1710+
}
1711+
16421712
static int qcom_pcie_probe(struct platform_device *pdev)
16431713
{
16441714
struct device *dev = &pdev->dev;
@@ -1699,6 +1769,10 @@ static int qcom_pcie_probe(struct platform_device *pdev)
16991769
goto err_pm_runtime_put;
17001770
}
17011771

1772+
ret = qcom_pcie_icc_init(pcie);
1773+
if (ret)
1774+
goto err_pm_runtime_put;
1775+
17021776
ret = pcie->cfg->ops->get_resources(pcie);
17031777
if (ret)
17041778
goto err_pm_runtime_put;
@@ -1717,6 +1791,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17171791
goto err_phy_exit;
17181792
}
17191793

1794+
qcom_pcie_icc_update(pcie);
1795+
17201796
return 0;
17211797

17221798
err_phy_exit:

0 commit comments

Comments
 (0)