[PATCH 2/9] coresight-etb: Adding runtime PM awareness
From: mathieu . poirier
Date: Tue Jan 06 2015 - 11:40:34 EST
From: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
Using the runtime API whenever HW access is required. As
such and by associating a coresight component to a power
domain in the device tree, faults associated to accessing
unpowered devices are mitigated.
Signed-off-by: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
---
drivers/coresight/coresight-etb10.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/coresight/coresight-etb10.c b/drivers/coresight/coresight-etb10.c
index c922d4aded8a..71fd6cdba21c 100644
--- a/drivers/coresight/coresight-etb10.c
+++ b/drivers/coresight/coresight-etb10.c
@@ -26,6 +26,7 @@
#include <linux/seq_file.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
+#include <linux/pm_runtime.h>
#include "coresight-priv.h"
@@ -92,17 +93,11 @@ struct etb_drvdata {
static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
{
- int ret;
u32 depth = 0;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
/* RO registers don't need locking */
depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
- clk_disable_unprepare(drvdata->clk);
return depth;
}
@@ -144,6 +139,7 @@ static int etb_enable(struct coresight_device *csdev)
if (ret)
return ret;
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
etb_enable_hw(drvdata);
drvdata->enable = true;
@@ -250,8 +246,9 @@ static void etb_disable(struct coresight_device *csdev)
etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
drvdata->enable = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ pm_runtime_put_sync(drvdata->dev);
clk_disable_unprepare(drvdata->clk);
dev_info(drvdata->dev, "ETB disabled\n");
@@ -266,10 +263,16 @@ static const struct coresight_ops etb_cs_ops = {
.sink_ops = &etb_sink_ops,
};
-static void etb_dump(struct etb_drvdata *drvdata)
+static int etb_dump(struct etb_drvdata *drvdata)
{
+ int ret;
unsigned long flags;
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->enable) {
etb_disable_hw(drvdata);
@@ -277,8 +280,11 @@ static void etb_dump(struct etb_drvdata *drvdata)
etb_enable_hw(drvdata);
}
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ pm_runtime_put_sync(drvdata->dev);
+ clk_disable_unprepare(drvdata->clk);
dev_info(drvdata->dev, "ETB dumped\n");
+ return 0;
}
static int etb_open(struct inode *inode, struct file *file)
@@ -296,11 +302,14 @@ static int etb_open(struct inode *inode, struct file *file)
static ssize_t etb_read(struct file *file, char __user *data,
size_t len, loff_t *ppos)
{
+ int ret;
u32 depth;
struct etb_drvdata *drvdata = container_of(file->private_data,
struct etb_drvdata, miscdev);
- etb_dump(drvdata);
+ ret = etb_dump(drvdata);
+ if (ret)
+ return ret;
depth = drvdata->buffer_depth;
if (*ppos + len > depth * 4)
@@ -349,6 +358,7 @@ static ssize_t status_show(struct device *dev,
if (ret)
goto out;
+ pm_runtime_get_sync(dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -363,7 +373,7 @@ static ssize_t status_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
+ pm_runtime_put_sync(dev);
clk_disable_unprepare(drvdata->clk);
return sprintf(buf,
@@ -486,6 +496,9 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
if (ret)
goto err_misc_register;
+ pm_runtime_set_suspended(dev);
+ pm_runtime_put_noidle(dev);
+
dev_info(dev, "ETB initialized\n");
return 0;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/