@@ -25,7 +25,6 @@ static const struct acpi_device_id amba_id_list[] = {
{"ARMHC501", 0}, /* ARM CoreSight ETR */
{"ARMHC502", 0}, /* ARM CoreSight STM */
{"ARMHC503", 0}, /* ARM CoreSight Debug */
- {"ARMHC979", 0}, /* ARM CoreSight TPIU */
{"ARMHC97C", 0}, /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */
{"", 0},
};
@@ -5,17 +5,19 @@
* Description: CoreSight Trace Port Interface Unit driver
*/
+#include <linux/acpi.h>
+#include <linux/amba/bus.h>
#include <linux/atomic.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
#include <linux/device.h>
-#include <linux/io.h>
#include <linux/err.h>
-#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-#include <linux/clk.h>
+#include <linux/slab.h>
#include "coresight-priv.h"
@@ -52,11 +54,13 @@ DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
/*
* @base: memory mapped base address for this component.
* @atclk: optional clock for the core parts of the TPIU.
+ * @pclk: APB clock if present, otherwise NULL
* @csdev: component vitals needed by the framework.
*/
struct tpiu_drvdata {
void __iomem *base;
struct clk *atclk;
+ struct clk *pclk;
struct coresight_device *csdev;
spinlock_t spinlock;
};
@@ -122,14 +126,12 @@ static const struct coresight_ops tpiu_cs_ops = {
.sink_ops = &tpiu_sink_ops,
};
-static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
+static int __tpiu_probe(struct device *dev, struct resource *res)
{
int ret;
void __iomem *base;
- struct device *dev = &adev->dev;
struct coresight_platform_data *pdata = NULL;
struct tpiu_drvdata *drvdata;
- struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
desc.name = coresight_alloc_device_name(&tpiu_devs, dev);
@@ -142,12 +144,16 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
- drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+ drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
+
+ drvdata->pclk = coresight_get_enable_apb_pclk(dev);
+ if (IS_ERR(drvdata->pclk))
+ return -ENODEV;
dev_set_drvdata(dev, drvdata);
/* Validity for the resource is already checked by the AMBA core */
@@ -173,21 +179,34 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
desc.dev = dev;
drvdata->csdev = coresight_register(&desc);
- if (!IS_ERR(drvdata->csdev)) {
- pm_runtime_put(&adev->dev);
+ if (!IS_ERR(drvdata->csdev))
return 0;
- }
return PTR_ERR(drvdata->csdev);
}
-static void tpiu_remove(struct amba_device *adev)
+static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
+{
+ int ret;
+
+ ret = __tpiu_probe(&adev->dev, &adev->res);
+ if (!ret)
+ pm_runtime_put(&adev->dev);
+ return ret;
+}
+
+static void __tpiu_remove(struct device *dev)
{
- struct tpiu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);
coresight_unregister(drvdata->csdev);
}
+static void tpiu_remove(struct amba_device *adev)
+{
+ __tpiu_remove(&adev->dev);
+}
+
#ifdef CONFIG_PM
static int tpiu_runtime_suspend(struct device *dev)
{
@@ -196,6 +215,8 @@ static int tpiu_runtime_suspend(struct device *dev)
if (drvdata && !IS_ERR(drvdata->atclk))
clk_disable_unprepare(drvdata->atclk);
+ if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+ clk_disable_unprepare(drvdata->pclk);
return 0;
}
@@ -206,6 +227,8 @@ static int tpiu_runtime_resume(struct device *dev)
if (drvdata && !IS_ERR(drvdata->atclk))
clk_prepare_enable(drvdata->atclk);
+ if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+ clk_prepare_enable(drvdata->pclk);
return 0;
}
#endif
@@ -245,7 +268,67 @@ static struct amba_driver tpiu_driver = {
.id_table = tpiu_ids,
};
-module_amba_driver(tpiu_driver);
+static int tpiu_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 = __tpiu_probe(&pdev->dev, res);
+ pm_runtime_put(&pdev->dev);
+ if (ret)
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static int tpiu_platform_remove(struct platform_device *pdev)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+ if (WARN_ON(!drvdata))
+ return -ENODEV;
+
+ __tpiu_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 tpiu_acpi_ids[] = {
+ {"ARMHC979", 0, 0, 0}, /* ARM CoreSight TPIU */
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, tpiu_acpi_ids);
+#endif
+
+static struct platform_driver tpiu_platform_driver = {
+ .probe = tpiu_platform_probe,
+ .remove = tpiu_platform_remove,
+ .driver = {
+ .name = "coresight-tpiu-platform",
+ .acpi_match_table = ACPI_PTR(tpiu_acpi_ids),
+ .suppress_bind_attrs = true,
+ .pm = &tpiu_dev_pm_ops,
+ },
+};
+
+static int __init tpiu_init(void)
+{
+ return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver);
+}
+
+static void __exit tpiu_exit(void)
+{
+ coresight_remove_driver(&tpiu_driver, &tpiu_platform_driver);
+}
+module_init(tpiu_init);
+module_exit(tpiu_exit);
MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");