Merge branch 'remotes/lorenzo/pci/qcom'
- Add DT and driver support for SC8280XP/SA8540P basic interconnects where interconnect bandwidth must be requested before enabling interconnect clocks (Johan Hovold) - Add 'dma-coherent' property (Johan Hovold) * remotes/lorenzo/pci/qcom: dt-bindings: PCI: qcom: Allow 'dma-coherent' property PCI: qcom: Add basic interconnect support dt-bindings: PCI: qcom: Add SC8280XP/SA8540P interconnects
This commit is contained in:
commit
008ee711f9
|
@ -62,6 +62,16 @@ properties:
|
|||
minItems: 3
|
||||
maxItems: 13
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
interconnects:
|
||||
maxItems: 2
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: pcie-mem
|
||||
- const: cpu-pcie
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 12
|
||||
|
@ -631,6 +641,18 @@ allOf:
|
|||
items:
|
||||
- const: pci # PCIe core reset
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pcie-sa8540p
|
||||
- qcom,pcie-sc8280xp
|
||||
then:
|
||||
required:
|
||||
- interconnects
|
||||
- interconnect-names
|
||||
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/crc8.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
@ -223,6 +224,7 @@ struct qcom_pcie {
|
|||
union qcom_pcie_resources res;
|
||||
struct phy *phy;
|
||||
struct gpio_desc *reset;
|
||||
struct icc_path *icc_mem;
|
||||
const struct qcom_pcie_cfg *cfg;
|
||||
};
|
||||
|
||||
|
@ -1639,6 +1641,74 @@ static const struct dw_pcie_ops dw_pcie_ops = {
|
|||
.start_link = qcom_pcie_start_link,
|
||||
};
|
||||
|
||||
static int qcom_pcie_icc_init(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
int ret;
|
||||
|
||||
pcie->icc_mem = devm_of_icc_get(pci->dev, "pcie-mem");
|
||||
if (IS_ERR(pcie->icc_mem))
|
||||
return PTR_ERR(pcie->icc_mem);
|
||||
|
||||
/*
|
||||
* Some Qualcomm platforms require interconnect bandwidth constraints
|
||||
* to be set before enabling interconnect clocks.
|
||||
*
|
||||
* Set an initial peak bandwidth corresponding to single-lane Gen 1
|
||||
* for the pcie-mem path.
|
||||
*/
|
||||
ret = icc_set_bw(pcie->icc_mem, 0, MBps_to_icc(250));
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_pcie_icc_update(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
u32 offset, status, bw;
|
||||
int speed, width;
|
||||
int ret;
|
||||
|
||||
if (!pcie->icc_mem)
|
||||
return;
|
||||
|
||||
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
|
||||
status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
|
||||
|
||||
/* Only update constraints if link is up. */
|
||||
if (!(status & PCI_EXP_LNKSTA_DLLLA))
|
||||
return;
|
||||
|
||||
speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, status);
|
||||
width = FIELD_GET(PCI_EXP_LNKSTA_NLW, status);
|
||||
|
||||
switch (speed) {
|
||||
case 1:
|
||||
bw = MBps_to_icc(250);
|
||||
break;
|
||||
case 2:
|
||||
bw = MBps_to_icc(500);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
fallthrough;
|
||||
case 3:
|
||||
bw = MBps_to_icc(985);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = icc_set_bw(pcie->icc_mem, 0, width * bw);
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -1699,6 +1769,10 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
goto err_pm_runtime_put;
|
||||
}
|
||||
|
||||
ret = qcom_pcie_icc_init(pcie);
|
||||
if (ret)
|
||||
goto err_pm_runtime_put;
|
||||
|
||||
ret = pcie->cfg->ops->get_resources(pcie);
|
||||
if (ret)
|
||||
goto err_pm_runtime_put;
|
||||
|
@ -1717,6 +1791,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
goto err_phy_exit;
|
||||
}
|
||||
|
||||
qcom_pcie_icc_update(pcie);
|
||||
|
||||
return 0;
|
||||
|
||||
err_phy_exit:
|
||||
|
|
Loading…
Reference in New Issue