|
@@ -18,6 +18,7 @@
|
|
|
#include <linux/io.h>
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/pm_runtime.h>
|
|
|
#include <linux/clk.h>
|
|
|
#include <linux/of.h>
|
|
|
#include <linux/coresight.h>
|
|
@@ -27,10 +28,12 @@
|
|
|
/**
|
|
|
* struct replicator_drvdata - specifics associated to a replicator component
|
|
|
* @dev: the device entity associated with this component
|
|
|
+ * @atclk: optional clock for the core parts of the replicator.
|
|
|
* @csdev: component vitals needed by the framework
|
|
|
*/
|
|
|
struct replicator_drvdata {
|
|
|
struct device *dev;
|
|
|
+ struct clk *atclk;
|
|
|
struct coresight_device *csdev;
|
|
|
};
|
|
|
|
|
@@ -39,6 +42,7 @@ static int replicator_enable(struct coresight_device *csdev, int inport,
|
|
|
{
|
|
|
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
|
|
|
|
|
+ pm_runtime_get_sync(drvdata->dev);
|
|
|
dev_info(drvdata->dev, "REPLICATOR enabled\n");
|
|
|
return 0;
|
|
|
}
|
|
@@ -48,6 +52,7 @@ static void replicator_disable(struct coresight_device *csdev, int inport,
|
|
|
{
|
|
|
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
|
|
|
|
|
+ pm_runtime_put(drvdata->dev);
|
|
|
dev_info(drvdata->dev, "REPLICATOR disabled\n");
|
|
|
}
|
|
|
|
|
@@ -62,6 +67,7 @@ static const struct coresight_ops replicator_cs_ops = {
|
|
|
|
|
|
static int replicator_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
+ int ret;
|
|
|
struct device *dev = &pdev->dev;
|
|
|
struct coresight_platform_data *pdata = NULL;
|
|
|
struct replicator_drvdata *drvdata;
|
|
@@ -80,11 +86,22 @@ static int replicator_probe(struct platform_device *pdev)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
drvdata->dev = &pdev->dev;
|
|
|
+ drvdata->atclk = devm_clk_get(&pdev->dev, "atclk"); /* optional */
|
|
|
+ if (!IS_ERR(drvdata->atclk)) {
|
|
|
+ ret = clk_prepare_enable(drvdata->atclk);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ pm_runtime_get_noresume(&pdev->dev);
|
|
|
+ pm_runtime_set_active(&pdev->dev);
|
|
|
+ pm_runtime_enable(&pdev->dev);
|
|
|
platform_set_drvdata(pdev, drvdata);
|
|
|
|
|
|
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
|
|
- if (!desc)
|
|
|
- return -ENOMEM;
|
|
|
+ if (!desc) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out_disable_pm;
|
|
|
+ }
|
|
|
|
|
|
desc->type = CORESIGHT_DEV_TYPE_LINK;
|
|
|
desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
|
|
@@ -92,11 +109,23 @@ static int replicator_probe(struct platform_device *pdev)
|
|
|
desc->pdata = pdev->dev.platform_data;
|
|
|
desc->dev = &pdev->dev;
|
|
|
drvdata->csdev = coresight_register(desc);
|
|
|
- if (IS_ERR(drvdata->csdev))
|
|
|
- return PTR_ERR(drvdata->csdev);
|
|
|
+ if (IS_ERR(drvdata->csdev)) {
|
|
|
+ ret = PTR_ERR(drvdata->csdev);
|
|
|
+ goto out_disable_pm;
|
|
|
+ }
|
|
|
+
|
|
|
+ pm_runtime_put(&pdev->dev);
|
|
|
|
|
|
dev_info(dev, "REPLICATOR initialized\n");
|
|
|
return 0;
|
|
|
+
|
|
|
+out_disable_pm:
|
|
|
+ if (!IS_ERR(drvdata->atclk))
|
|
|
+ clk_disable_unprepare(drvdata->atclk);
|
|
|
+ pm_runtime_put_noidle(&pdev->dev);
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int replicator_remove(struct platform_device *pdev)
|
|
@@ -104,9 +133,42 @@ static int replicator_remove(struct platform_device *pdev)
|
|
|
struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
|
|
|
|
|
|
coresight_unregister(drvdata->csdev);
|
|
|
+ pm_runtime_get_sync(&pdev->dev);
|
|
|
+ if (!IS_ERR(drvdata->atclk))
|
|
|
+ clk_disable_unprepare(drvdata->atclk);
|
|
|
+ pm_runtime_put_noidle(&pdev->dev);
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_PM
|
|
|
+static int replicator_runtime_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ struct replicator_drvdata *drvdata = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (drvdata && !IS_ERR(drvdata->atclk))
|
|
|
+ clk_disable_unprepare(drvdata->atclk);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int replicator_runtime_resume(struct device *dev)
|
|
|
+{
|
|
|
+ struct replicator_drvdata *drvdata = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (drvdata && !IS_ERR(drvdata->atclk))
|
|
|
+ clk_prepare_enable(drvdata->atclk);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static const struct dev_pm_ops replicator_dev_pm_ops = {
|
|
|
+ SET_RUNTIME_PM_OPS(replicator_runtime_suspend,
|
|
|
+ replicator_runtime_resume, NULL)
|
|
|
+};
|
|
|
+
|
|
|
static const struct of_device_id replicator_match[] = {
|
|
|
{.compatible = "arm,coresight-replicator"},
|
|
|
{}
|
|
@@ -118,6 +180,7 @@ static struct platform_driver replicator_driver = {
|
|
|
.driver = {
|
|
|
.name = "coresight-replicator",
|
|
|
.of_match_table = replicator_match,
|
|
|
+ .pm = &replicator_dev_pm_ops,
|
|
|
},
|
|
|
};
|
|
|
|