aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2015-05-05 13:42:29 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2015-05-05 13:42:29 +1000
commit774cb140b9b56edf85406895f35ce1643b1fc40c (patch)
tree3846c63d52c5eb91af2084e6296645e4c2c14de0
parent8d94592ce46671df704237827ffa71976e3aa78f (diff)
parent48582dcacc6b3af45aee8cdbf8fb1ac0c5d329d7 (diff)
Merge remote-tracking branch 'coresight/next'
-rw-r--r--Documentation/devicetree/bindings/arm/coresight.txt13
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c79
-rw-r--r--drivers/hwtracing/coresight/coresight-etm.h4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x.c112
-rw-r--r--drivers/hwtracing/coresight/coresight-funnel.c61
-rw-r--r--drivers/hwtracing/coresight/coresight-replicator.c71
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.c31
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c60
-rw-r--r--drivers/hwtracing/coresight/of_coresight.c2
9 files changed, 281 insertions, 152 deletions
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 88602b75418e..8711c1065479 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -21,11 +21,14 @@ its hardware characteristcs.
* reg: physical base address and length of the register
set(s) of the component.
- * clocks: the clock associated to this component.
-
- * clock-names: the name of the clock as referenced by the code.
- Since we are using the AMBA framework, the name should be
- "apb_pclk".
+ * clocks: the clocks associated to this component.
+
+ * clock-names: the name of the clocks referenced by the code.
+ Since we are using the AMBA framework, the name of the clock
+ providing the interconnect should be "apb_pclk", and some
+ coresight blocks also have an additional clock "atclk", which
+ clocks the core of that coresight component. The latter clock
+ is optional.
* port or ports: The representation of the component's port
layout using the generic DT graph presentation found in
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 40049869aecd..77d0f9c1118d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -22,10 +22,11 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
+#include <linux/clk.h>
#include "coresight-priv.h"
@@ -66,9 +67,9 @@
* struct etb_drvdata - specifics associated to an ETB component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
+ * @atclk: optional clock for the core parts of the ETB.
* @csdev: component vitals needed by the framework.
* @miscdev: specifics to handle "/dev/xyz.etb" entry.
- * @clk: the clock this component is associated to.
* @spinlock: only one at a time pls.
* @in_use: synchronise user space access to etb buffer.
* @buf: area of memory where ETB buffer content gets sent.
@@ -79,9 +80,9 @@
struct etb_drvdata {
void __iomem *base;
struct device *dev;
+ struct clk *atclk;
struct coresight_device *csdev;
struct miscdevice miscdev;
- struct clk *clk;
spinlock_t spinlock;
atomic_t in_use;
u8 *buf;
@@ -92,17 +93,14 @@ 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;
+ pm_runtime_get_sync(drvdata->dev);
/* RO registers don't need locking */
depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return depth;
}
@@ -137,12 +135,9 @@ static void etb_enable_hw(struct etb_drvdata *drvdata)
static int etb_enable(struct coresight_device *csdev)
{
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- 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);
etb_enable_hw(drvdata);
@@ -252,7 +247,7 @@ static void etb_disable(struct coresight_device *csdev)
drvdata->enable = false;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
dev_info(drvdata->dev, "ETB disabled\n");
}
@@ -339,16 +334,12 @@ static const struct file_operations etb_fops = {
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
unsigned long flags;
u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- goto out;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -364,7 +355,7 @@ static ssize_t status_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return sprintf(buf,
"Depth:\t\t0x%x\n"
@@ -377,7 +368,7 @@ static ssize_t status_show(struct device *dev,
"Flush ctrl:\t0x%x\n",
etb_rdr, etb_sr, etb_rrp, etb_rwp,
etb_trg, etb_cr, etb_ffsr, etb_ffcr);
-out:
+
return -EINVAL;
}
static DEVICE_ATTR_RO(status);
@@ -438,6 +429,12 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
return -ENOMEM;
drvdata->dev = &adev->dev;
+ drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+ if (!IS_ERR(drvdata->atclk)) {
+ ret = clk_prepare_enable(drvdata->atclk);
+ if (ret)
+ return ret;
+ }
dev_set_drvdata(dev, drvdata);
/* validity for the resource is already checked by the AMBA core */
@@ -449,21 +446,19 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
- drvdata->clk = adev->pclk;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
- if (drvdata->buffer_depth < 0)
+ if (drvdata->buffer_depth & 0x80000000)
return -EINVAL;
drvdata->buf = devm_kzalloc(dev,
drvdata->buffer_depth * 4, GFP_KERNEL);
- if (!drvdata->buf)
+ if (!drvdata->buf) {
+ dev_err(dev, "Failed to allocate %u bytes for buffer data\n",
+ drvdata->buffer_depth * 4);
return -ENOMEM;
+ }
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
@@ -503,6 +498,32 @@ static int etb_remove(struct amba_device *adev)
return 0;
}
+#ifdef CONFIG_PM
+static int etb_runtime_suspend(struct device *dev)
+{
+ struct etb_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata && !IS_ERR(drvdata->atclk))
+ clk_disable_unprepare(drvdata->atclk);
+
+ return 0;
+}
+
+static int etb_runtime_resume(struct device *dev)
+{
+ struct etb_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 etb_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(etb_runtime_suspend, etb_runtime_resume, NULL)
+};
+
static struct amba_id etb_ids[] = {
{
.id = 0x0003b907,
@@ -515,6 +536,8 @@ static struct amba_driver etb_driver = {
.drv = {
.name = "coresight-etb10",
.owner = THIS_MODULE,
+ .pm = &etb_dev_pm_ops,
+
},
.probe = etb_probe,
.remove = etb_remove,
diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index 501c5fac8a45..098ffbec0a44 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -140,8 +140,8 @@
* struct etm_drvdata - specifics associated to an ETM component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
+ * @atclk: optional clock for the core parts of the ETM.
* @csdev: component vitals needed by the framework.
- * @clk: the clock this component is associated to.
* @spinlock: only one at a time pls.
* @cpu: the cpu this component is affined to.
* @port_size: port size as reported by ETMCR bit 4-6 and 21.
@@ -192,8 +192,8 @@
struct etm_drvdata {
void __iomem *base;
struct device *dev;
+ struct clk *atclk;
struct coresight_device *csdev;
- struct clk *clk;
spinlock_t spinlock;
int cpu;
int port_size;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index c965f5724abd..018a00fda611 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -23,13 +23,14 @@
#include <linux/smp.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/cpu.h>
#include <linux/of.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
+#include <linux/clk.h>
#include <asm/sections.h>
#include "coresight-etm.h"
@@ -325,9 +326,7 @@ static int etm_trace_id(struct coresight_device *csdev)
if (!drvdata->enable)
return drvdata->traceid;
-
- if (clk_prepare_enable(drvdata->clk))
- goto out;
+ pm_runtime_get_sync(csdev->dev.parent);
spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -336,8 +335,8 @@ static int etm_trace_id(struct coresight_device *csdev)
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
-out:
+ pm_runtime_put(csdev->dev.parent);
+
return trace_id;
}
@@ -346,10 +345,7 @@ static int etm_enable(struct coresight_device *csdev)
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- goto err_clk;
-
+ pm_runtime_get_sync(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
/*
@@ -373,8 +369,7 @@ static int etm_enable(struct coresight_device *csdev)
return 0;
err:
spin_unlock(&drvdata->spinlock);
- clk_disable_unprepare(drvdata->clk);
-err_clk:
+ pm_runtime_put(csdev->dev.parent);
return ret;
}
@@ -423,8 +418,7 @@ static void etm_disable(struct coresight_device *csdev)
spin_unlock(&drvdata->spinlock);
put_online_cpus();
-
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(csdev->dev.parent);
dev_info(drvdata->dev, "ETM tracing disabled\n");
}
@@ -474,14 +468,10 @@ static DEVICE_ATTR_RO(nr_ctxid_cmp);
static ssize_t etmsr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
unsigned long flags, val;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -489,7 +479,7 @@ static ssize_t etmsr_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return sprintf(buf, "%#lx\n", val);
}
@@ -1317,7 +1307,6 @@ static DEVICE_ATTR_RW(seq_13_event);
static ssize_t seq_curr_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
unsigned long val, flags;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
@@ -1326,10 +1315,7 @@ static ssize_t seq_curr_state_show(struct device *dev,
goto out;
}
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -1337,7 +1323,7 @@ static ssize_t seq_curr_state_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
out:
return sprintf(buf, "%#lx\n", val);
}
@@ -1521,10 +1507,7 @@ static ssize_t status_show(struct device *dev,
unsigned long flags;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -1550,7 +1533,7 @@ static ssize_t status_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return ret;
}
@@ -1559,7 +1542,6 @@ static DEVICE_ATTR_RO(status);
static ssize_t traceid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
unsigned long val, flags;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
@@ -1568,10 +1550,7 @@ static ssize_t traceid_show(struct device *dev,
goto out;
}
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -1579,7 +1558,7 @@ static ssize_t traceid_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
out:
return sprintf(buf, "%#lx\n", val);
}
@@ -1817,10 +1796,12 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
- drvdata->clk = adev->pclk;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
+ drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+ if (!IS_ERR(drvdata->atclk)) {
+ ret = clk_prepare_enable(drvdata->atclk);
+ if (ret)
+ return ret;
+ }
drvdata->cpu = pdata ? pdata->cpu : 0;
@@ -1845,8 +1826,6 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
}
etm_init_default_data(drvdata);
- clk_disable_unprepare(drvdata->clk);
-
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &etm_cs_ops;
@@ -1859,7 +1838,8 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
goto err_arch_supported;
}
- dev_info(dev, "ETM initialized\n");
+ pm_runtime_put(&adev->dev);
+ dev_info(dev, "%s initialized\n", (char *)id->data);
if (boot_enable) {
coresight_enable(drvdata->csdev);
@@ -1869,7 +1849,6 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
return 0;
err_arch_supported:
- clk_disable_unprepare(drvdata->clk);
if (--etm_count == 0)
unregister_hotcpu_notifier(&etm_cpu_notifier);
return ret;
@@ -1886,22 +1865,52 @@ static int etm_remove(struct amba_device *adev)
return 0;
}
+#ifdef CONFIG_PM
+static int etm_runtime_suspend(struct device *dev)
+{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata && !IS_ERR(drvdata->atclk))
+ clk_disable_unprepare(drvdata->atclk);
+
+ return 0;
+}
+
+static int etm_runtime_resume(struct device *dev)
+{
+ struct etm_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 etm_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(etm_runtime_suspend, etm_runtime_resume, NULL)
+};
+
static struct amba_id etm_ids[] = {
{ /* ETM 3.3 */
.id = 0x0003b921,
.mask = 0x0003ffff,
+ .data = "ETM 3.3",
},
{ /* ETM 3.5 */
.id = 0x0003b956,
.mask = 0x0003ffff,
+ .data = "ETM 3.5",
},
{ /* PTM 1.0 */
.id = 0x0003b950,
.mask = 0x0003ffff,
+ .data = "PTM 1.0",
},
{ /* PTM 1.1 */
.id = 0x0003b95f,
.mask = 0x0003ffff,
+ .data = "PTM 1.1",
},
{ 0, 0},
};
@@ -1910,23 +1919,14 @@ static struct amba_driver etm_driver = {
.drv = {
.name = "coresight-etm3x",
.owner = THIS_MODULE,
+ .pm = &etm_dev_pm_ops,
},
.probe = etm_probe,
.remove = etm_remove,
.id_table = etm_ids,
};
-int __init etm_init(void)
-{
- return amba_driver_register(&etm_driver);
-}
-module_init(etm_init);
-
-void __exit etm_exit(void)
-{
- amba_driver_unregister(&etm_driver);
-}
-module_exit(etm_exit);
+module_amba_driver(etm_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 3db36f70b666..2e36bde7fcb4 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -18,9 +18,10 @@
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/slab.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
+#include <linux/clk.h>
#include "coresight-priv.h"
@@ -35,15 +36,15 @@
* struct funnel_drvdata - specifics associated to a funnel component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
+ * @atclk: optional clock for the core parts of the funnel.
* @csdev: component vitals needed by the framework.
- * @clk: the clock this component is associated to.
* @priority: port selection order.
*/
struct funnel_drvdata {
void __iomem *base;
struct device *dev;
+ struct clk *atclk;
struct coresight_device *csdev;
- struct clk *clk;
unsigned long priority;
};
@@ -67,12 +68,8 @@ static int funnel_enable(struct coresight_device *csdev, int inport,
int outport)
{
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
+ pm_runtime_get_sync(drvdata->dev);
funnel_enable_hw(drvdata, inport);
dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
@@ -98,8 +95,7 @@ static void funnel_disable(struct coresight_device *csdev, int inport,
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
funnel_disable_hw(drvdata, inport);
-
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
}
@@ -153,16 +149,14 @@ static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata)
static ssize_t funnel_ctrl_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
u32 val;
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
+ pm_runtime_get_sync(drvdata->dev);
val = get_funnel_ctrl_hw(drvdata);
- clk_disable_unprepare(drvdata->clk);
+
+ pm_runtime_put(drvdata->dev);
return sprintf(buf, "%#x\n", val);
}
@@ -177,6 +171,7 @@ ATTRIBUTE_GROUPS(coresight_funnel);
static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
{
+ int ret;
void __iomem *base;
struct device *dev = &adev->dev;
struct coresight_platform_data *pdata = NULL;
@@ -197,6 +192,12 @@ static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
return -ENOMEM;
drvdata->dev = &adev->dev;
+ drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+ if (!IS_ERR(drvdata->atclk)) {
+ ret = clk_prepare_enable(drvdata->atclk);
+ if (ret)
+ return ret;
+ }
dev_set_drvdata(dev, drvdata);
/* Validity for the resource is already checked by the AMBA core */
@@ -205,8 +206,7 @@ static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);
drvdata->base = base;
-
- drvdata->clk = adev->pclk;
+ pm_runtime_put(&adev->dev);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
@@ -234,6 +234,32 @@ static int funnel_remove(struct amba_device *adev)
return 0;
}
+#ifdef CONFIG_PM
+static int funnel_runtime_suspend(struct device *dev)
+{
+ struct funnel_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata && !IS_ERR(drvdata->atclk))
+ clk_disable_unprepare(drvdata->atclk);
+
+ return 0;
+}
+
+static int funnel_runtime_resume(struct device *dev)
+{
+ struct funnel_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 funnel_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(funnel_runtime_suspend, funnel_runtime_resume, NULL)
+};
+
static struct amba_id funnel_ids[] = {
{
.id = 0x0003b908,
@@ -246,6 +272,7 @@ static struct amba_driver funnel_driver = {
.drv = {
.name = "coresight-funnel",
.owner = THIS_MODULE,
+ .pm = &funnel_dev_pm_ops,
},
.probe = funnel_probe,
.remove = funnel_remove,
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 75b9abd804e6..7974b7c3da6b 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -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,
},
};
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 7147f3dd363c..a57c7ec1661f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
@@ -104,7 +104,6 @@ enum tmc_mem_intf_width {
* @dev: the device entity associated to this component.
* @csdev: component vitals needed by the framework.
* @miscdev: specifics to handle "/dev/xyz.tmc" entry.
- * @clk: the clock this component is associated to.
* @spinlock: only one at a time pls.
* @read_count: manages preparation of buffer for reading.
* @buf: area of memory where trace data get sent.
@@ -120,7 +119,6 @@ struct tmc_drvdata {
struct device *dev;
struct coresight_device *csdev;
struct miscdevice miscdev;
- struct clk *clk;
spinlock_t spinlock;
int read_count;
bool reading;
@@ -242,17 +240,14 @@ static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
{
- 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->reading) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return -EBUSY;
}
@@ -386,7 +381,7 @@ out:
drvdata->enable = false;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
dev_info(drvdata->dev, "TMC disabled\n");
}
@@ -568,17 +563,13 @@ static const struct file_operations tmc_fops = {
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
unsigned long flags;
u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
u32 devid;
struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- goto out;
-
+ pm_runtime_get_sync(drvdata->dev);
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
@@ -596,8 +587,7 @@ static ssize_t status_show(struct device *dev,
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
return sprintf(buf,
"Depth:\t\t0x%x\n"
@@ -613,7 +603,7 @@ static ssize_t status_show(struct device *dev,
"DEVID:\t\t0x%x\n",
tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
-out:
+
return -EINVAL;
}
static DEVICE_ATTR_RO(status);
@@ -700,11 +690,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
- drvdata->clk = adev->pclk;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
drvdata->config_type = BMVAL(devid, 6, 7);
@@ -719,7 +704,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
}
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 3b33af2416bb..7214efd10db5 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -17,9 +17,10 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
+#include <linux/clk.h>
#include "coresight-priv.h"
@@ -50,14 +51,14 @@
/**
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
+ * @atclk: optional clock for the core parts of the TPIU.
* @csdev: component vitals needed by the framework.
- * @clk: the clock this component is associated to.
*/
struct tpiu_drvdata {
void __iomem *base;
struct device *dev;
+ struct clk *atclk;
struct coresight_device *csdev;
- struct clk *clk;
};
static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
@@ -72,12 +73,8 @@ static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
static int tpiu_enable(struct coresight_device *csdev)
{
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
+ pm_runtime_get_sync(csdev->dev.parent);
tpiu_enable_hw(drvdata);
dev_info(drvdata->dev, "TPIU enabled\n");
@@ -101,8 +98,7 @@ static void tpiu_disable(struct coresight_device *csdev)
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
tpiu_disable_hw(drvdata);
-
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(csdev->dev.parent);
dev_info(drvdata->dev, "TPIU disabled\n");
}
@@ -139,6 +135,12 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
return -ENOMEM;
drvdata->dev = &adev->dev;
+ drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+ if (!IS_ERR(drvdata->atclk)) {
+ ret = clk_prepare_enable(drvdata->atclk);
+ if (ret)
+ return ret;
+ }
dev_set_drvdata(dev, drvdata);
/* Validity for the resource is already checked by the AMBA core */
@@ -148,15 +150,10 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->base = base;
- drvdata->clk = adev->pclk;
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
/* Disable tpiu to support older devices */
tpiu_disable_hw(drvdata);
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
@@ -183,11 +180,41 @@ static int tpiu_remove(struct amba_device *adev)
return 0;
}
+#ifdef CONFIG_PM
+static int tpiu_runtime_suspend(struct device *dev)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata && !IS_ERR(drvdata->atclk))
+ clk_disable_unprepare(drvdata->atclk);
+
+ return 0;
+}
+
+static int tpiu_runtime_resume(struct device *dev)
+{
+ struct tpiu_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 tpiu_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(tpiu_runtime_suspend, tpiu_runtime_resume, NULL)
+};
+
static struct amba_id tpiu_ids[] = {
{
.id = 0x0003b912,
.mask = 0x0003ffff,
},
+ {
+ .id = 0x0004b912,
+ .mask = 0x0007ffff,
+ },
{ 0, 0},
};
@@ -195,6 +222,7 @@ static struct amba_driver tpiu_driver = {
.drv = {
.name = "coresight-tpiu",
.owner = THIS_MODULE,
+ .pm = &tpiu_dev_pm_ops,
},
.probe = tpiu_probe,
.remove = tpiu_remove,
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
index 35e51ce93a5c..b0973617826f 100644
--- a/drivers/hwtracing/coresight/of_coresight.c
+++ b/drivers/hwtracing/coresight/of_coresight.c
@@ -37,7 +37,7 @@ of_coresight_get_endpoint_device(struct device_node *endpoint)
struct device *dev = NULL;
/*
- * If we have a non-configuable replicator, it will be found on the
+ * If we have a non-configurable replicator, it will be found on the
* platform bus.
*/
dev = bus_find_device(&platform_bus_type, NULL,