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>
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+
630674static 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+
695753err_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