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
2 changed files with 98 additions and 0 deletions
|
@ -62,6 +62,16 @@ properties:
|
||||||
minItems: 3
|
minItems: 3
|
||||||
maxItems: 13
|
maxItems: 13
|
||||||
|
|
||||||
|
dma-coherent: true
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: pcie-mem
|
||||||
|
- const: cpu-pcie
|
||||||
|
|
||||||
resets:
|
resets:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 12
|
maxItems: 12
|
||||||
|
@ -631,6 +641,18 @@ allOf:
|
||||||
items:
|
items:
|
||||||
- const: pci # PCIe core reset
|
- const: pci # PCIe core reset
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- qcom,pcie-sa8540p
|
||||||
|
- qcom,pcie-sc8280xp
|
||||||
|
then:
|
||||||
|
required:
|
||||||
|
- interconnects
|
||||||
|
- interconnect-names
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
not:
|
not:
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/crc8.h>
|
#include <linux/crc8.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/interconnect.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
|
@ -223,6 +224,7 @@ struct qcom_pcie {
|
||||||
union qcom_pcie_resources res;
|
union qcom_pcie_resources res;
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
struct gpio_desc *reset;
|
struct gpio_desc *reset;
|
||||||
|
struct icc_path *icc_mem;
|
||||||
const struct qcom_pcie_cfg *cfg;
|
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,
|
.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)
|
static int qcom_pcie_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
@ -1699,6 +1769,10 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
||||||
goto err_pm_runtime_put;
|
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);
|
ret = pcie->cfg->ops->get_resources(pcie);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_pm_runtime_put;
|
goto err_pm_runtime_put;
|
||||||
|
@ -1717,6 +1791,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
||||||
goto err_phy_exit;
|
goto err_phy_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qcom_pcie_icc_update(pcie);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_phy_exit:
|
err_phy_exit:
|
||||||
|
|
Loading…
Add table
Reference in a new issue