Skip to content

Commit 6dbba2b

Browse files
Mani-SadhasivamLorenzo Pieralisi
authored andcommitted
PCI: qcom-ep: Expose link transition counts via debugfs
Qualcomm PCIe controllers have debug registers in the MMIO region that count PCIe link transitions. Expose them over debugfs to userspace to help debug the low power issues. Link: https://lore.kernel.org/r/20220914075350.7992-6-manivannan.sadhasivam@linaro.org Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
1 parent 19619b4 commit 6dbba2b

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include <linux/clk.h>
13+
#include <linux/debugfs.h>
1314
#include <linux/delay.h>
1415
#include <linux/gpio/consumer.h>
1516
#include <linux/mfd/syscon.h>
@@ -45,6 +46,11 @@
4546
#define PARF_ATU_BASE_ADDR 0x634
4647
#define PARF_ATU_BASE_ADDR_HI 0x638
4748
#define PARF_SRIS_MODE 0x644
49+
#define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04
50+
#define PARF_DEBUG_CNT_PM_LINKST_IN_L1 0xc0c
51+
#define PARF_DEBUG_CNT_PM_LINKST_IN_L0S 0xc10
52+
#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0xc84
53+
#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0xc88
4854
#define PARF_DEVICE_TYPE 0x1000
4955
#define PARF_BDF_TO_SID_CFG 0x2c00
5056

@@ -135,12 +141,14 @@ enum qcom_pcie_ep_link_status {
135141
* @pci: Designware PCIe controller struct
136142
* @parf: Qualcomm PCIe specific PARF register base
137143
* @elbi: Designware PCIe specific ELBI register base
144+
* @mmio: MMIO register base
138145
* @perst_map: PERST regmap
139146
* @mmio_res: MMIO region resource
140147
* @core_reset: PCIe Endpoint core reset
141148
* @reset: PERST# GPIO
142149
* @wake: WAKE# GPIO
143150
* @phy: PHY controller block
151+
* @debugfs: PCIe Endpoint Debugfs directory
144152
* @clks: PCIe clocks
145153
* @num_clks: PCIe clocks count
146154
* @perst_en: Flag for PERST enable
@@ -154,13 +162,15 @@ struct qcom_pcie_ep {
154162

155163
void __iomem *parf;
156164
void __iomem *elbi;
165+
void __iomem *mmio;
157166
struct regmap *perst_map;
158167
struct resource *mmio_res;
159168

160169
struct reset_control *core_reset;
161170
struct gpio_desc *reset;
162171
struct gpio_desc *wake;
163172
struct phy *phy;
173+
struct dentry *debugfs;
164174

165175
struct clk_bulk_data *clks;
166176
int num_clks;
@@ -446,6 +456,9 @@ static int qcom_pcie_ep_get_io_resources(struct platform_device *pdev,
446456

447457
pcie_ep->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
448458
"mmio");
459+
pcie_ep->mmio = devm_pci_remap_cfg_resource(dev, pcie_ep->mmio_res);
460+
if (IS_ERR(pcie_ep->mmio))
461+
return PTR_ERR(pcie_ep->mmio);
449462

450463
syscon = of_parse_phandle(dev->of_node, "qcom,perst-regs", 0);
451464
if (!syscon) {
@@ -627,6 +640,37 @@ static int qcom_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
627640
}
628641
}
629642

643+
static int qcom_pcie_ep_link_transition_count(struct seq_file *s, void *data)
644+
{
645+
struct qcom_pcie_ep *pcie_ep = (struct qcom_pcie_ep *)
646+
dev_get_drvdata(s->private);
647+
648+
seq_printf(s, "L0s transition count: %u\n",
649+
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L0S));
650+
651+
seq_printf(s, "L1 transition count: %u\n",
652+
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L1));
653+
654+
seq_printf(s, "L1.1 transition count: %u\n",
655+
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1));
656+
657+
seq_printf(s, "L1.2 transition count: %u\n",
658+
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2));
659+
660+
seq_printf(s, "L2 transition count: %u\n",
661+
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L2));
662+
663+
return 0;
664+
}
665+
666+
static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep)
667+
{
668+
struct dw_pcie *pci = &pcie_ep->pci;
669+
670+
debugfs_create_devm_seqfile(pci->dev, "link_transition_count", pcie_ep->debugfs,
671+
qcom_pcie_ep_link_transition_count);
672+
}
673+
630674
static const struct pci_epc_features qcom_pcie_epc_features = {
631675
.linkup_notifier = true,
632676
.core_init_notifier = true,
@@ -659,6 +703,7 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
659703
{
660704
struct device *dev = &pdev->dev;
661705
struct qcom_pcie_ep *pcie_ep;
706+
char *name;
662707
int ret;
663708

664709
pcie_ep = devm_kzalloc(dev, sizeof(*pcie_ep), GFP_KERNEL);
@@ -690,8 +735,21 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
690735
if (ret)
691736
goto err_disable_resources;
692737

738+
name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
739+
if (!name) {
740+
ret = -ENOMEM;
741+
goto err_disable_irqs;
742+
}
743+
744+
pcie_ep->debugfs = debugfs_create_dir(name, NULL);
745+
qcom_pcie_ep_init_debugfs(pcie_ep);
746+
693747
return 0;
694748

749+
err_disable_irqs:
750+
disable_irq(pcie_ep->global_irq);
751+
disable_irq(pcie_ep->perst_irq);
752+
695753
err_disable_resources:
696754
qcom_pcie_disable_resources(pcie_ep);
697755

@@ -705,6 +763,8 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)
705763
disable_irq(pcie_ep->global_irq);
706764
disable_irq(pcie_ep->perst_irq);
707765

766+
debugfs_remove_recursive(pcie_ep->debugfs);
767+
708768
if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED)
709769
return 0;
710770

0 commit comments

Comments
 (0)