coresight: debug: Move ACPI support from AMBA driver to platform driver
authorAnshuman Khandual <anshuman.khandual@arm.com>
Thu, 14 Mar 2024 05:58:43 +0000 (11:28 +0530)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Tue, 16 Apr 2024 10:30:47 +0000 (11:30 +0100)
Add support for the cpu debug devices in a new platform driver, which can
then be used on ACPI based platforms. This change would now allow runtime
power management for ACPI based systems. The driver would try to enable
the APB clock if available. But first this renames and then refactors
debug_probe() and debug_remove(), making sure they can be used both for
platform and AMBA drivers.

Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: James Clark <james.clark@arm.com>
Cc: linux-acpi@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: coresight@lists.linaro.org
Acked-by: Sudeep Holla <sudeep.holla@arm.com> # For ACPI related changes
Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20240314055843.2625883-12-anshuman.khandual@arm.com
drivers/acpi/arm64/amba.c
drivers/hwtracing/coresight/coresight-cpu-debug.c

index bec0976541da0ec8ca4e4518a7f9ee3623a808db..e1f0bbb8f3938877540da84f7c07f4119873759d 100644 (file)
@@ -22,7 +22,6 @@
 static const struct acpi_device_id amba_id_list[] = {
        {"ARMH0061", 0}, /* PL061 GPIO Device */
        {"ARMH0330", 0}, /* ARM DMA Controller DMA-330 */
-       {"ARMHC503", 0}, /* ARM CoreSight Debug */
        {"", 0},
 };
 
index 1874df7c6a7369f8f52f3f8c13e2455c2b68e7bf..3263fc86cb6621b4bcefe442bb87d0736816e651 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Author: Leo Yan <leo.yan@linaro.org>
  */
+#include <linux/acpi.h>
 #include <linux/amba/bus.h>
 #include <linux/coresight.h>
 #include <linux/cpu.h>
@@ -18,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/panic_notifier.h>
+#include <linux/platform_device.h>
 #include <linux/pm_qos.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -84,6 +86,7 @@
 #define DEBUG_WAIT_TIMEOUT             32000
 
 struct debug_drvdata {
+       struct clk      *pclk;
        void __iomem    *base;
        struct device   *dev;
        int             cpu;
@@ -557,18 +560,12 @@ static void debug_func_exit(void)
        debugfs_remove_recursive(debug_debugfs_dir);
 }
 
-static int debug_probe(struct amba_device *adev, const struct amba_id *id)
+static int __debug_probe(struct device *dev, struct resource *res)
 {
+       struct debug_drvdata *drvdata = dev_get_drvdata(dev);
        void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct debug_drvdata *drvdata;
-       struct resource *res = &adev->res;
        int ret;
 
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
        drvdata->cpu = coresight_get_cpu(dev);
        if (drvdata->cpu < 0)
                return drvdata->cpu;
@@ -579,10 +576,7 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id)
                return -EBUSY;
        }
 
-       drvdata->dev = &adev->dev;
-       amba_set_drvdata(adev, drvdata);
-
-       /* Validity for the resource is already checked by the AMBA core */
+       drvdata->dev = dev;
        base = devm_ioremap_resource(dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
@@ -629,10 +623,21 @@ err:
        return ret;
 }
 
-static void debug_remove(struct amba_device *adev)
+static int debug_probe(struct amba_device *adev, const struct amba_id *id)
 {
-       struct device *dev = &adev->dev;
-       struct debug_drvdata *drvdata = amba_get_drvdata(adev);
+       struct debug_drvdata *drvdata;
+
+       drvdata = devm_kzalloc(&adev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       amba_set_drvdata(adev, drvdata);
+       return __debug_probe(&adev->dev, &adev->res);
+}
+
+static void __debug_remove(struct device *dev)
+{
+       struct debug_drvdata *drvdata = dev_get_drvdata(dev);
 
        per_cpu(debug_drvdata, drvdata->cpu) = NULL;
 
@@ -646,6 +651,11 @@ static void debug_remove(struct amba_device *adev)
                debug_func_exit();
 }
 
+static void debug_remove(struct amba_device *adev)
+{
+       __debug_remove(&adev->dev);
+}
+
 static const struct amba_cs_uci_id uci_id_debug[] = {
        {
                /*  CPU Debug UCI data */
@@ -677,7 +687,103 @@ static struct amba_driver debug_driver = {
        .id_table       = debug_ids,
 };
 
-module_amba_driver(debug_driver);
+static int debug_platform_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct debug_drvdata *drvdata;
+       int ret = 0;
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->pclk = coresight_get_enable_apb_pclk(&pdev->dev);
+       if (IS_ERR(drvdata->pclk))
+               return -ENODEV;
+
+       dev_set_drvdata(&pdev->dev, drvdata);
+       pm_runtime_get_noresume(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
+       ret = __debug_probe(&pdev->dev, res);
+       if (ret) {
+               pm_runtime_put_noidle(&pdev->dev);
+               pm_runtime_disable(&pdev->dev);
+               if (!IS_ERR_OR_NULL(drvdata->pclk))
+                       clk_put(drvdata->pclk);
+       }
+       return ret;
+}
+
+static int debug_platform_remove(struct platform_device *pdev)
+{
+       struct debug_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+       if (WARN_ON(!drvdata))
+               return -ENODEV;
+
+       __debug_remove(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       if (!IS_ERR_OR_NULL(drvdata->pclk))
+               clk_put(drvdata->pclk);
+       return 0;
+}
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id debug_platform_ids[] = {
+       {"ARMHC503", 0, 0, 0}, /* ARM CoreSight Debug */
+       {},
+};
+MODULE_DEVICE_TABLE(acpi, debug_platform_ids);
+#endif
+
+#ifdef CONFIG_PM
+static int debug_runtime_suspend(struct device *dev)
+{
+       struct debug_drvdata *drvdata = dev_get_drvdata(dev);
+
+       if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+               clk_disable_unprepare(drvdata->pclk);
+       return 0;
+}
+
+static int debug_runtime_resume(struct device *dev)
+{
+       struct debug_drvdata *drvdata = dev_get_drvdata(dev);
+
+       if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+               clk_prepare_enable(drvdata->pclk);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops debug_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(debug_runtime_suspend, debug_runtime_resume, NULL)
+};
+
+static struct platform_driver debug_platform_driver = {
+       .probe  = debug_platform_probe,
+       .remove = debug_platform_remove,
+       .driver = {
+               .name                   = "coresight-debug-platform",
+               .acpi_match_table       = ACPI_PTR(debug_platform_ids),
+               .suppress_bind_attrs    = true,
+               .pm                     = &debug_dev_pm_ops,
+       },
+};
+
+static int __init debug_init(void)
+{
+       return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
+}
+
+static void __exit debug_exit(void)
+{
+       coresight_remove_driver(&debug_driver, &debug_platform_driver);
+}
+module_init(debug_init);
+module_exit(debug_exit);
 
 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
 MODULE_DESCRIPTION("ARM Coresight CPU Debug Driver");