Skip to content

Commit 2195c16

Browse files
committed
Merge branch 'pci/controller/qcom-ep'
- Log unknown Qcom Endpoint IRQ events at error level, not debug level (Manivannan Sadhasivam) - Add DT and driver support for qcom interconnect bandwidth voting for "pcie-mem" and "cpu-pcie" interconnects (Krishna chaitanya chundru) * pci/controller/qcom-ep: PCI: qcom-ep: Add ICC bandwidth voting support dt-bindings: PCI: qcom: ep: Add interconnects path PCI: qcom-ep: Treat unknown IRQ events as an error
2 parents e8ce465 + 0179423 commit 2195c16

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ properties:
7474
description: GPIO used as WAKE# output signal
7575
maxItems: 1
7676

77+
interconnects:
78+
maxItems: 2
79+
80+
interconnect-names:
81+
items:
82+
- const: pcie-mem
83+
- const: cpu-pcie
84+
7785
resets:
7886
maxItems: 1
7987

@@ -101,6 +109,8 @@ required:
101109
- interrupts
102110
- interrupt-names
103111
- reset-gpios
112+
- interconnects
113+
- interconnect-names
104114
- resets
105115
- reset-names
106116
- power-domains
@@ -169,7 +179,9 @@ examples:
169179
- |
170180
#include <dt-bindings/clock/qcom,gcc-sdx55.h>
171181
#include <dt-bindings/gpio/gpio.h>
182+
#include <dt-bindings/interconnect/qcom,sdx55.h>
172183
#include <dt-bindings/interrupt-controller/arm-gic.h>
184+
173185
pcie_ep: pcie-ep@1c00000 {
174186
compatible = "qcom,sdx55-pcie-ep";
175187
reg = <0x01c00000 0x3000>,
@@ -196,6 +208,9 @@ examples:
196208
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
197209
<GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
198210
interrupt-names = "global", "doorbell";
211+
interconnects = <&system_noc MASTER_PCIE &mc_virt SLAVE_EBI_CH0>,
212+
<&mem_noc MASTER_AMPSS_M0 &system_noc SLAVE_PCIE_0>;
213+
interconnect-names = "pcie-mem", "cpu-pcie";
199214
reset-gpios = <&tlmm 57 GPIO_ACTIVE_LOW>;
200215
wake-gpios = <&tlmm 53 GPIO_ACTIVE_LOW>;
201216
resets = <&gcc GCC_PCIE_BCR>;

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

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/debugfs.h>
1414
#include <linux/delay.h>
1515
#include <linux/gpio/consumer.h>
16+
#include <linux/interconnect.h>
1617
#include <linux/mfd/syscon.h>
1718
#include <linux/phy/pcie.h>
1819
#include <linux/phy/phy.h>
@@ -134,6 +135,11 @@
134135
#define CORE_RESET_TIME_US_MAX 1005
135136
#define WAKE_DELAY_US 2000 /* 2 ms */
136137

138+
#define PCIE_GEN1_BW_MBPS 250
139+
#define PCIE_GEN2_BW_MBPS 500
140+
#define PCIE_GEN3_BW_MBPS 985
141+
#define PCIE_GEN4_BW_MBPS 1969
142+
137143
#define to_pcie_ep(x) dev_get_drvdata((x)->dev)
138144

139145
enum qcom_pcie_ep_link_status {
@@ -156,6 +162,7 @@ enum qcom_pcie_ep_link_status {
156162
* @wake: WAKE# GPIO
157163
* @phy: PHY controller block
158164
* @debugfs: PCIe Endpoint Debugfs directory
165+
* @icc_mem: Handle to an interconnect path between PCIe and MEM
159166
* @clks: PCIe clocks
160167
* @num_clks: PCIe clocks count
161168
* @perst_en: Flag for PERST enable
@@ -179,6 +186,8 @@ struct qcom_pcie_ep {
179186
struct phy *phy;
180187
struct dentry *debugfs;
181188

189+
struct icc_path *icc_mem;
190+
182191
struct clk_bulk_data *clks;
183192
int num_clks;
184193

@@ -254,8 +263,49 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pci)
254263
disable_irq(pcie_ep->perst_irq);
255264
}
256265

266+
static void qcom_pcie_ep_icc_update(struct qcom_pcie_ep *pcie_ep)
267+
{
268+
struct dw_pcie *pci = &pcie_ep->pci;
269+
u32 offset, status, bw;
270+
int speed, width;
271+
int ret;
272+
273+
if (!pcie_ep->icc_mem)
274+
return;
275+
276+
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
277+
status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
278+
279+
speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, status);
280+
width = FIELD_GET(PCI_EXP_LNKSTA_NLW, status);
281+
282+
switch (speed) {
283+
case 1:
284+
bw = MBps_to_icc(PCIE_GEN1_BW_MBPS);
285+
break;
286+
case 2:
287+
bw = MBps_to_icc(PCIE_GEN2_BW_MBPS);
288+
break;
289+
case 3:
290+
bw = MBps_to_icc(PCIE_GEN3_BW_MBPS);
291+
break;
292+
default:
293+
dev_warn(pci->dev, "using default GEN4 bandwidth\n");
294+
fallthrough;
295+
case 4:
296+
bw = MBps_to_icc(PCIE_GEN4_BW_MBPS);
297+
break;
298+
}
299+
300+
ret = icc_set_bw(pcie_ep->icc_mem, 0, width * bw);
301+
if (ret)
302+
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
303+
ret);
304+
}
305+
257306
static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
258307
{
308+
struct dw_pcie *pci = &pcie_ep->pci;
259309
int ret;
260310

261311
ret = clk_bulk_prepare_enable(pcie_ep->num_clks, pcie_ep->clks);
@@ -278,8 +328,24 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
278328
if (ret)
279329
goto err_phy_exit;
280330

331+
/*
332+
* Some Qualcomm platforms require interconnect bandwidth constraints
333+
* to be set before enabling interconnect clocks.
334+
*
335+
* Set an initial peak bandwidth corresponding to single-lane Gen 1
336+
* for the pcie-mem path.
337+
*/
338+
ret = icc_set_bw(pcie_ep->icc_mem, 0, MBps_to_icc(PCIE_GEN1_BW_MBPS));
339+
if (ret) {
340+
dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
341+
ret);
342+
goto err_phy_off;
343+
}
344+
281345
return 0;
282346

347+
err_phy_off:
348+
phy_power_off(pcie_ep->phy);
283349
err_phy_exit:
284350
phy_exit(pcie_ep->phy);
285351
err_disable_clk:
@@ -290,6 +356,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
290356

291357
static void qcom_pcie_disable_resources(struct qcom_pcie_ep *pcie_ep)
292358
{
359+
icc_set_bw(pcie_ep->icc_mem, 0, 0);
293360
phy_power_off(pcie_ep->phy);
294361
phy_exit(pcie_ep->phy);
295362
clk_bulk_disable_unprepare(pcie_ep->num_clks, pcie_ep->clks);
@@ -551,6 +618,10 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
551618
if (IS_ERR(pcie_ep->phy))
552619
ret = PTR_ERR(pcie_ep->phy);
553620

621+
pcie_ep->icc_mem = devm_of_icc_get(dev, "pcie-mem");
622+
if (IS_ERR(pcie_ep->icc_mem))
623+
ret = PTR_ERR(pcie_ep->icc_mem);
624+
554625
return ret;
555626
}
556627

@@ -574,6 +645,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
574645
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
575646
dev_dbg(dev, "Received BME event. Link is enabled!\n");
576647
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
648+
qcom_pcie_ep_icc_update(pcie_ep);
577649
pci_epc_bme_notify(pci->ep.epc);
578650
} else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) {
579651
dev_dbg(dev, "Received PM Turn-off event! Entering L23\n");
@@ -594,7 +666,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
594666
dw_pcie_ep_linkup(&pci->ep);
595667
pcie_ep->link_status = QCOM_PCIE_EP_LINK_UP;
596668
} else {
597-
dev_dbg(dev, "Received unknown event: %d\n", status);
669+
dev_err(dev, "Received unknown event: %d\n", status);
598670
}
599671

600672
return IRQ_HANDLED;

0 commit comments

Comments
 (0)