diff mbox series

[v2,2/3] PCI: dwc: Add sysfs support for PTM context

Message ID 20250324-pcie-ptm-v2-2-c7d8c3644b4a@linaro.org (mailing list archive)
State New
Delegated to: Krzysztof WilczyƄski
Headers show
Series PCI: Add PTM sysfs support | expand

Commit Message

Manivannan Sadhasivam March 24, 2025, 10:04 a.m. UTC
From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Synopsys Designware PCIe IPs support PTM capability as defined in the PCIe
spec r6.0, sec 6.22. The PTM context information is exposed through Vendor
Specific Extended Capability (VSEC) registers on supported controller
implementation.

Hence, add support for exposing these context information to userspace
through the sysfs interface for the DWC controllers (both RC and EP).
Currently, only Qcom controllers are supported. For adding support for
DWC vendor controllers, dwc_pcie_ptm_vsec_ids[] needs to be extended.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 drivers/pci/controller/dwc/Makefile                |   2 +-
 drivers/pci/controller/dwc/pcie-designware-ep.c    |   3 +
 drivers/pci/controller/dwc/pcie-designware-host.c  |   3 +
 drivers/pci/controller/dwc/pcie-designware-sysfs.c | 254 +++++++++++++++++++++
 drivers/pci/controller/dwc/pcie-designware.c       |   6 +
 drivers/pci/controller/dwc/pcie-designware.h       |  21 ++
 include/linux/pcie-dwc.h                           |   8 +
 7 files changed, 296 insertions(+), 1 deletion(-)

Comments

kernel test robot March 24, 2025, 2:06 p.m. UTC | #1
Hi Manivannan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 1f5a69f1b3132054d8d82b8d7546d0af6a2ed4f6]

url:    https://github.com/intel-lab-lkp/linux/commits/Manivannan-Sadhasivam-via-B4-Relay/PCI-Add-sysfs-support-for-exposing-PTM-context/20250324-181039
base:   1f5a69f1b3132054d8d82b8d7546d0af6a2ed4f6
patch link:    https://lore.kernel.org/r/20250324-pcie-ptm-v2-2-c7d8c3644b4a%40linaro.org
patch subject: [PATCH v2 2/3] PCI: dwc: Add sysfs support for PTM context
config: csky-randconfig-001-20250324 (https://download.01.org/0day-ci/archive/20250324/202503242112.lOewj3sy-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250324/202503242112.lOewj3sy-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503242112.lOewj3sy-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/perf/dwc_pcie_pmu.c:16:
>> include/linux/pcie-dwc.h:38:38: warning: 'dwc_pcie_ptm_vsec_ids' defined but not used [-Wunused-const-variable=]
      38 | static const struct dwc_pcie_vsec_id dwc_pcie_ptm_vsec_ids[] = {
         |                                      ^~~~~~~~~~~~~~~~~~~~~


vim +/dwc_pcie_ptm_vsec_ids +38 include/linux/pcie-dwc.h

    37	
  > 38	static const struct dwc_pcie_vsec_id dwc_pcie_ptm_vsec_ids[] = {
    39		{ .vendor_id = PCI_VENDOR_ID_QCOM, /* EP */
    40		  .vsec_id = 0x03, .vsec_rev = 0x1 },
    41		{ .vendor_id = PCI_VENDOR_ID_QCOM, /* RC */
    42		  .vsec_id = 0x04, .vsec_rev = 0x1 },
    43		{ }
    44	};
    45
kernel test robot March 26, 2025, 9:42 p.m. UTC | #2
Hi Manivannan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 1f5a69f1b3132054d8d82b8d7546d0af6a2ed4f6]

url:    https://github.com/intel-lab-lkp/linux/commits/Manivannan-Sadhasivam-via-B4-Relay/PCI-Add-sysfs-support-for-exposing-PTM-context/20250324-181039
base:   1f5a69f1b3132054d8d82b8d7546d0af6a2ed4f6
patch link:    https://lore.kernel.org/r/20250324-pcie-ptm-v2-2-c7d8c3644b4a%40linaro.org
patch subject: [PATCH v2 2/3] PCI: dwc: Add sysfs support for PTM context
config: i386-randconfig-062-20250326 (https://download.01.org/0day-ci/archive/20250327/202503270545.z7lzaIQz-lkp@intel.com/config)
compiler: clang version 20.1.1 (https://github.com/llvm/llvm-project 424c2d9b7e4de40d0804dd374721e6411c27d1d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250327/202503270545.z7lzaIQz-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503270545.z7lzaIQz-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/pci/controller/dwc/pcie-designware-sysfs.c:222:21: sparse: sparse: symbol 'dw_pcie_ptm_ops' was not declared. Should it be static?

vim +/dw_pcie_ptm_ops +222 drivers/pci/controller/dwc/pcie-designware-sysfs.c

   221	
 > 222	struct pcie_ptm_ops dw_pcie_ptm_ops = {
   223		.check_capability = dw_pcie_ptm_check_capability,
   224		.context_update_store = dw_pcie_ptm_context_update_store,
   225		.context_update_show = dw_pcie_ptm_context_update_show,
   226		.context_valid_store = dw_pcie_ptm_context_valid_store,
   227		.context_valid_show = dw_pcie_ptm_context_valid_show,
   228		.local_clock_show = dw_pcie_ptm_local_clock_show,
   229		.master_clock_show = dw_pcie_ptm_master_clock_show,
   230		.t1_show = dw_pcie_ptm_t1_show,
   231		.t2_show = dw_pcie_ptm_t2_show,
   232		.t3_show = dw_pcie_ptm_t3_show,
   233		.t4_show = dw_pcie_ptm_t4_show,
   234		.context_update_visible = dw_pcie_ptm_context_update_visible,
   235		.context_valid_visible = dw_pcie_ptm_context_valid_visible,
   236		.local_clock_visible = dw_pcie_ptm_local_clock_visible,
   237		.master_clock_visible = dw_pcie_ptm_master_clock_visible,
   238		.t1_visible = dw_pcie_ptm_t1_visible,
   239		.t2_visible = dw_pcie_ptm_t2_visible,
   240		.t3_visible = dw_pcie_ptm_t3_visible,
   241		.t4_visible = dw_pcie_ptm_t4_visible,
   242	};
   243
diff mbox series

Patch

diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 54565eedc52cc36bc393e257d093c4671aff7b39..ca7c1ff7a6807bf0aec24778dc10c02c7e8680c7 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -1,5 +1,5 @@ 
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_PCIE_DW) += pcie-designware.o
+obj-$(CONFIG_PCIE_DW) += pcie-designware.o pcie-designware-sysfs.o
 obj-$(CONFIG_PCIE_DW_DEBUGFS) += pcie-designware-debugfs.o
 obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o
 obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 5a6174e107c20c897cfa142687e219c5ecafb8c6..d1a07cebc4c21f1a81048730bcf40fa8e1dba0b1 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -705,6 +705,7 @@  void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
+	pcie_designware_sysfs_exit(pci);
 	dwc_pcie_debugfs_deinit(pci);
 	dw_pcie_edma_remove(pci);
 }
@@ -880,6 +881,8 @@  int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
 
 	dwc_pcie_debugfs_init(pci);
 
+	pcie_designware_sysfs_init(pci, DW_PCIE_EP_TYPE);
+
 	return 0;
 
 err_remove_edma:
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 6501fb062c70e56eb301ca71fcd642f7be33a252..faaabc5446ebde5adcdf5ab03e0cf3569636b79b 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -550,6 +550,8 @@  int dw_pcie_host_init(struct dw_pcie_rp *pp)
 
 	dwc_pcie_debugfs_init(pci);
 
+	pcie_designware_sysfs_init(pci, DW_PCIE_RC_TYPE);
+
 	return 0;
 
 err_stop_link:
@@ -574,6 +576,7 @@  void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 
+	pcie_designware_sysfs_exit(pci);
 	dwc_pcie_debugfs_deinit(pci);
 
 	pci_stop_root_bus(pp->bridge->bus);
diff --git a/drivers/pci/controller/dwc/pcie-designware-sysfs.c b/drivers/pci/controller/dwc/pcie-designware-sysfs.c
new file mode 100644
index 0000000000000000000000000000000000000000..1723444e408c90dee0c8d0b526c6887969451d6c
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-designware-sysfs.c
@@ -0,0 +1,254 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "pcie-designware.h"
+
+static int dw_pcie_ptm_check_capability(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	pci->ptm_vsec_offset = dw_pcie_find_ptm_capability(pci);
+
+	return pci->ptm_vsec_offset;
+}
+
+static int dw_pcie_ptm_context_update_store(void *drvdata, const char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 val;
+
+	if (sysfs_streq(buf, "auto")) {
+		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+		val |= PTM_REQ_AUTO_UPDATE_ENABLED;
+		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
+	} else if (sysfs_streq(buf, "manual")) {
+		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+		val &= ~PTM_REQ_AUTO_UPDATE_ENABLED;
+		val |= PTM_REQ_START_UPDATE;
+		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static ssize_t dw_pcie_ptm_context_update_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 val;
+
+	val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+	if (FIELD_GET(PTM_REQ_AUTO_UPDATE_ENABLED, val))
+		return sysfs_emit(buf, "auto\n");
+
+	/*
+	 * PTM_REQ_START_UPDATE is a self clearing register bit. So if
+	 * PTM_REQ_AUTO_UPDATE_ENABLED is not set, then it implies that
+	 * manual update is used.
+	 */
+	return sysfs_emit(buf, "manual\n");
+}
+
+static int dw_pcie_ptm_context_valid_store(void *drvdata, bool valid)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 val;
+
+	if (valid) {
+		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+		val |= PTM_RES_CCONTEXT_VALID;
+		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
+	} else {
+		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+		val &= ~PTM_RES_CCONTEXT_VALID;
+		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
+	}
+
+	return 0;
+}
+
+static ssize_t dw_pcie_ptm_context_valid_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 val;
+
+	val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
+
+	return sysfs_emit(buf, "%u\n", !!FIELD_GET(PTM_RES_CCONTEXT_VALID, val));
+}
+
+static ssize_t dw_pcie_ptm_local_clock_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static ssize_t dw_pcie_ptm_master_clock_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static ssize_t dw_pcie_ptm_t1_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static ssize_t dw_pcie_ptm_t2_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static ssize_t dw_pcie_ptm_t3_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static ssize_t dw_pcie_ptm_t4_show(void *drvdata, char *buf)
+{
+	struct dw_pcie *pci = drvdata;
+	u32 msb, lsb;
+
+	do {
+		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB);
+		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB);
+	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB));
+
+	return sysfs_emit(buf, "%llu\n", ((u64) msb) << 32 | lsb);
+}
+
+static bool dw_pcie_ptm_context_update_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_context_valid_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_local_clock_visible(void *drvdata)
+{
+	/* PTM local clock is always visible */
+	return true;
+}
+
+static bool dw_pcie_ptm_master_clock_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_t1_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_t2_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_t3_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
+}
+
+static bool dw_pcie_ptm_t4_visible(void *drvdata)
+{
+	struct dw_pcie *pci = drvdata;
+
+	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
+}
+
+struct pcie_ptm_ops dw_pcie_ptm_ops = {
+	.check_capability = dw_pcie_ptm_check_capability,
+	.context_update_store = dw_pcie_ptm_context_update_store,
+	.context_update_show = dw_pcie_ptm_context_update_show,
+	.context_valid_store = dw_pcie_ptm_context_valid_store,
+	.context_valid_show = dw_pcie_ptm_context_valid_show,
+	.local_clock_show = dw_pcie_ptm_local_clock_show,
+	.master_clock_show = dw_pcie_ptm_master_clock_show,
+	.t1_show = dw_pcie_ptm_t1_show,
+	.t2_show = dw_pcie_ptm_t2_show,
+	.t3_show = dw_pcie_ptm_t3_show,
+	.t4_show = dw_pcie_ptm_t4_show,
+	.context_update_visible = dw_pcie_ptm_context_update_visible,
+	.context_valid_visible = dw_pcie_ptm_context_valid_visible,
+	.local_clock_visible = dw_pcie_ptm_local_clock_visible,
+	.master_clock_visible = dw_pcie_ptm_master_clock_visible,
+	.t1_visible = dw_pcie_ptm_t1_visible,
+	.t2_visible = dw_pcie_ptm_t2_visible,
+	.t3_visible = dw_pcie_ptm_t3_visible,
+	.t4_visible = dw_pcie_ptm_t4_visible,
+};
+
+void pcie_designware_sysfs_init(struct dw_pcie *pci,
+				    enum dw_pcie_device_mode mode)
+{
+	pci->mode = mode;
+	pcie_ptm_create_sysfs(pci->dev, pci, &dw_pcie_ptm_ops);
+}
+
+void pcie_designware_sysfs_exit(struct dw_pcie *pci)
+{
+	pcie_ptm_destroy_sysfs();
+}
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 3d1d95d9e38057dd1389e2d57d701ce4f4fa6f7f..1e858c15991f0f87e0711b9a9eec9c44d43fef4b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -329,6 +329,12 @@  u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_find_rasdes_capability);
 
+u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci)
+{
+	return dw_pcie_find_vsec_capability(pci, dwc_pcie_ptm_vsec_ids);
+}
+EXPORT_SYMBOL_GPL(dw_pcie_find_ptm_capability);
+
 int dw_pcie_read(void __iomem *addr, int size, u32 *val)
 {
 	if (!IS_ALIGNED((uintptr_t)addr, size)) {
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 2d1de81d47b67fc0df941484b1d92d986b2b4dbd..27a729b9c13f17dd635bc2976a0b5d4c7aeff5f9 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -260,6 +260,21 @@ 
 
 #define PCIE_RAS_DES_EVENT_COUNTER_DATA		0xc
 
+/* PTM register definitions */
+#define PTM_RES_REQ_CTRL		0x8
+#define PTM_RES_CCONTEXT_VALID		BIT(0)
+#define PTM_REQ_AUTO_UPDATE_ENABLED	BIT(0)
+#define PTM_REQ_START_UPDATE		BIT(1)
+
+#define PTM_LOCAL_LSB			0x10
+#define PTM_LOCAL_MSB			0x14
+#define PTM_T1_T2_LSB			0x18
+#define PTM_T1_T2_MSB			0x1c
+#define PTM_T3_T4_LSB			0x28
+#define PTM_T3_T4_MSB			0x2c
+#define PTM_MASTER_LSB			0x38
+#define PTM_MASTER_MSB			0x3c
+
 /*
  * The default address offset between dbi_base and atu_base. Root controller
  * drivers are not required to initialize atu_base if the offset matches this
@@ -500,6 +515,8 @@  struct dw_pcie {
 	struct reset_control_bulk_data	app_rsts[DW_PCIE_NUM_APP_RSTS];
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
 	struct gpio_desc		*pe_rst;
+	u16			ptm_vsec_offset;
+	enum			dw_pcie_device_mode mode;
 	bool			suspended;
 	struct debugfs_info	*debugfs;
 };
@@ -516,6 +533,7 @@  void dw_pcie_version_detect(struct dw_pcie *pci);
 u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap);
 u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap);
 u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci);
+u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci);
 
 int dw_pcie_read(void __iomem *addr, int size, u32 *val);
 int dw_pcie_write(void __iomem *addr, int size, u32 val);
@@ -537,6 +555,9 @@  void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
+void pcie_designware_sysfs_init(struct dw_pcie *pci,
+				enum dw_pcie_device_mode mode);
+void pcie_designware_sysfs_exit(struct dw_pcie *pci);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {
diff --git a/include/linux/pcie-dwc.h b/include/linux/pcie-dwc.h
index 8ff778e7aec0ef60462ea69245c76a91c81b76b9..b15057fa6c0ef1794b72c9279b49787fe56302c4 100644
--- a/include/linux/pcie-dwc.h
+++ b/include/linux/pcie-dwc.h
@@ -35,4 +35,12 @@  static const struct dwc_pcie_vsec_id dwc_pcie_rasdes_vsec_ids[] = {
 	{}
 };
 
+static const struct dwc_pcie_vsec_id dwc_pcie_ptm_vsec_ids[] = {
+	{ .vendor_id = PCI_VENDOR_ID_QCOM, /* EP */
+	  .vsec_id = 0x03, .vsec_rev = 0x1 },
+	{ .vendor_id = PCI_VENDOR_ID_QCOM, /* RC */
+	  .vsec_id = 0x04, .vsec_rev = 0x1 },
+	{ }
+};
+
 #endif /* LINUX_PCIE_DWC_H */