]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
coresight: tpdm: add static tpdm support
authorJie Gan <jie.gan@oss.qualcomm.com>
Tue, 28 Oct 2025 10:11:41 +0000 (18:11 +0800)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Thu, 6 Nov 2025 11:37:05 +0000 (11:37 +0000)
The static TPDM function as a dummy source, however, it is essential
to enable the port connected to the TPDA and configure the element size.
Without this, the TPDA cannot correctly receive trace data from the
static TPDM. Since the static TPDM does not require MMIO mapping to
access its registers, a clock controller is not mandatory for its
operation.

Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20251028-add_static_tpdm_support-v4-2-84e21b98e727@oss.qualcomm.com
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
drivers/hwtracing/coresight/coresight-tpda.c
drivers/hwtracing/coresight/coresight-tpdm.c
drivers/hwtracing/coresight/coresight-tpdm.h

index 333b3cb236859f0feb1498f4ab81037c772143fd..3a3825d27f861585ca1d847929747f8096004089 100644 (file)
 
 DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
 
-static bool coresight_device_is_tpdm(struct coresight_device *csdev)
-{
-       return (coresight_is_device_source(csdev)) &&
-              (csdev->subtype.source_subtype ==
-                       CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
-}
-
 static void tpda_clear_element_size(struct coresight_device *csdev)
 {
        struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
index 7214e65097ec9ac69f6c7c9278bcd28d25945c9e..0e3896c12f0706d0c0e563153b81297a817876b7 100644 (file)
@@ -470,6 +470,9 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
  */
 static void __tpdm_enable(struct tpdm_drvdata *drvdata)
 {
+       if (coresight_is_static_tpdm(drvdata->csdev))
+               return;
+
        CS_UNLOCK(drvdata->base);
 
        tpdm_enable_dsb(drvdata);
@@ -532,6 +535,9 @@ static void tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
 /* TPDM disable operations */
 static void __tpdm_disable(struct tpdm_drvdata *drvdata)
 {
+       if (coresight_is_static_tpdm(drvdata->csdev))
+               return;
+
        CS_UNLOCK(drvdata->base);
 
        tpdm_disable_dsb(drvdata);
@@ -595,6 +601,30 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata)
        return 0;
 }
 
+static int static_tpdm_datasets_setup(struct tpdm_drvdata *drvdata, struct device *dev)
+{
+       /* setup datasets for static TPDM */
+       if (fwnode_property_present(dev->fwnode, "qcom,dsb-element-bits") &&
+           (!drvdata->dsb)) {
+               drvdata->dsb = devm_kzalloc(drvdata->dev,
+                                               sizeof(*drvdata->dsb), GFP_KERNEL);
+
+               if (!drvdata->dsb)
+                       return -ENOMEM;
+       }
+
+       if (fwnode_property_present(dev->fwnode, "qcom,cmb-element-bits") &&
+           (!drvdata->cmb)) {
+               drvdata->cmb = devm_kzalloc(drvdata->dev,
+                                               sizeof(*drvdata->cmb), GFP_KERNEL);
+
+               if (!drvdata->cmb)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static ssize_t reset_dataset_store(struct device *dev,
                                   struct device_attribute *attr,
                                   const char *buf,
@@ -1342,10 +1372,9 @@ static const struct attribute_group *tpdm_attr_grps[] = {
        NULL,
 };
 
-static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
+static int tpdm_probe(struct device *dev, struct resource *res)
 {
        void __iomem *base;
-       struct device *dev = &adev->dev;
        struct coresight_platform_data *pdata;
        struct tpdm_drvdata *drvdata;
        struct coresight_desc desc = { 0 };
@@ -1354,32 +1383,37 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
        pdata = coresight_get_platform_data(dev);
        if (IS_ERR(pdata))
                return PTR_ERR(pdata);
-       adev->dev.platform_data = pdata;
+       dev->platform_data = pdata;
 
        /* driver data*/
        drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
        if (!drvdata)
                return -ENOMEM;
-       drvdata->dev = &adev->dev;
+       drvdata->dev = dev;
        dev_set_drvdata(dev, drvdata);
 
-       base = devm_ioremap_resource(dev, &adev->res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
+       if (res) {
+               base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(base))
+                       return PTR_ERR(base);
 
-       drvdata->base = base;
+               drvdata->base = base;
+               ret = tpdm_datasets_setup(drvdata);
+               if (ret)
+                       return ret;
 
-       ret = tpdm_datasets_setup(drvdata);
-       if (ret)
-               return ret;
-
-       if (drvdata && tpdm_has_dsb_dataset(drvdata))
-               of_property_read_u32(drvdata->dev->of_node,
-                          "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
+               if (drvdata && tpdm_has_dsb_dataset(drvdata))
+                       of_property_read_u32(drvdata->dev->of_node,
+                                            "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
 
-       if (drvdata && tpdm_has_cmb_dataset(drvdata))
-               of_property_read_u32(drvdata->dev->of_node,
-                          "qcom,cmb-msrs-num", &drvdata->cmb_msr_num);
+               if (drvdata && tpdm_has_cmb_dataset(drvdata))
+                       of_property_read_u32(drvdata->dev->of_node,
+                                            "qcom,cmb-msrs-num", &drvdata->cmb_msr_num);
+       } else {
+               ret = static_tpdm_datasets_setup(drvdata, dev);
+               if (ret)
+                       return ret;
+       }
 
        /* Set up coresight component description */
        desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
@@ -1388,34 +1422,51 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
        desc.type = CORESIGHT_DEV_TYPE_SOURCE;
        desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM;
        desc.ops = &tpdm_cs_ops;
-       desc.pdata = adev->dev.platform_data;
-       desc.dev = &adev->dev;
+       desc.pdata = dev->platform_data;
+       desc.dev = dev;
        desc.access = CSDEV_ACCESS_IOMEM(base);
-       desc.groups = tpdm_attr_grps;
+       if (res)
+               desc.groups = tpdm_attr_grps;
        drvdata->csdev = coresight_register(&desc);
        if (IS_ERR(drvdata->csdev))
                return PTR_ERR(drvdata->csdev);
 
        spin_lock_init(&drvdata->spinlock);
 
-       /* Decrease pm refcount when probe is done.*/
-       pm_runtime_put(&adev->dev);
-
        return 0;
 }
 
-static void tpdm_remove(struct amba_device *adev)
+static int tpdm_remove(struct device *dev)
 {
-       struct tpdm_drvdata *drvdata = dev_get_drvdata(&adev->dev);
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(dev);
 
        coresight_unregister(drvdata->csdev);
+
+       return 0;
+}
+
+static int dynamic_tpdm_probe(struct amba_device *adev,
+                             const struct amba_id *id)
+{
+       int ret;
+
+       ret = tpdm_probe(&adev->dev, &adev->res);
+       if (!ret)
+               pm_runtime_put(&adev->dev);
+
+       return ret;
+}
+
+static void dynamic_tpdm_remove(struct amba_device *adev)
+{
+       tpdm_remove(&adev->dev);
 }
 
 /*
  * Different TPDM has different periph id.
  * The difference is 0-7 bits' value. So ignore 0-7 bits.
  */
-static const struct amba_id tpdm_ids[] = {
+static const struct amba_id dynamic_tpdm_ids[] = {
        {
                .id     = 0x001f0e00,
                .mask   = 0x00ffff00,
@@ -1423,17 +1474,76 @@ static const struct amba_id tpdm_ids[] = {
        { 0, 0, NULL },
 };
 
-static struct amba_driver tpdm_driver = {
+MODULE_DEVICE_TABLE(amba, dynamic_tpdm_ids);
+
+static struct amba_driver dynamic_tpdm_driver = {
        .drv = {
                .name   = "coresight-tpdm",
                .suppress_bind_attrs = true,
        },
-       .probe          = tpdm_probe,
-       .id_table       = tpdm_ids,
-       .remove         = tpdm_remove,
+       .probe          = dynamic_tpdm_probe,
+       .id_table       = dynamic_tpdm_ids,
+       .remove         = dynamic_tpdm_remove,
 };
 
-module_amba_driver(tpdm_driver);
+static int tpdm_platform_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int ret;
+
+       pm_runtime_get_noresume(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
+       ret = tpdm_probe(&pdev->dev, res);
+       pm_runtime_put(&pdev->dev);
+       if (ret)
+               pm_runtime_disable(&pdev->dev);
+
+       return ret;
+}
+
+static void tpdm_platform_remove(struct platform_device *pdev)
+{
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+       if (WARN_ON(!drvdata))
+               return;
+
+       tpdm_remove(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id static_tpdm_match[] = {
+       {.compatible = "qcom,coresight-static-tpdm"},
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, static_tpdm_match);
+
+static struct platform_driver static_tpdm_driver = {
+       .probe          = tpdm_platform_probe,
+       .remove         = tpdm_platform_remove,
+       .driver         = {
+               .name   = "coresight-static-tpdm",
+               .of_match_table = static_tpdm_match,
+               .suppress_bind_attrs = true,
+       },
+};
+
+static int __init tpdm_init(void)
+{
+       return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver,
+                                    THIS_MODULE);
+}
+
+static void __exit tpdm_exit(void)
+{
+       coresight_remove_driver(&dynamic_tpdm_driver, &static_tpdm_driver);
+}
+
+module_init(tpdm_init);
+module_exit(tpdm_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
index b117543897344b689f666f6890cabb59c8ee4869..2867f3ab818618fb6cf7f4eb6baa72b4f85edaf5 100644 (file)
@@ -343,4 +343,16 @@ struct tpdm_dataset_attribute {
        enum dataset_mem mem;
        u32 idx;
 };
+
+static inline bool coresight_device_is_tpdm(struct coresight_device *csdev)
+{
+       return (coresight_is_device_source(csdev)) &&
+               (csdev->subtype.source_subtype ==
+                       CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
+}
+
+static inline bool coresight_is_static_tpdm(struct coresight_device *csdev)
+{
+       return (coresight_device_is_tpdm(csdev) && !csdev->access.base);
+}
 #endif  /* _CORESIGHT_CORESIGHT_TPDM_H */