summaryrefslogtreecommitdiff
path: root/drivers/perf
diff options
context:
space:
mode:
authorJoakim Zhang <qiangqing.zhang@nxp.com>2020-02-27 17:23:49 +0800
committerJoakim Zhang <qiangqing.zhang@nxp.com>2020-03-04 09:06:04 +0800
commit3ed9ecdd13bad3b17244e501f5c7af219bbdee54 (patch)
treed7095517444debcad3697f71ee868a623d72ae64 /drivers/perf
parent6c8278b52ab6c03198b9c29c705d28e933305aa0 (diff)
MLK-23418-3 perf/imx_ddr: Add clock support for Perf in DB
Add clock support for Perf in DB SS, since Perf LPCG has the clocks off by default. Reviewed-by: Fugang Duan <fugang.duan@nxp.com> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Diffstat (limited to 'drivers/perf')
-rw-r--r--drivers/perf/fsl_imx8_ddr_perf.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
index 4e816dfc5117..ef33224db95a 100644
--- a/drivers/perf/fsl_imx8_ddr_perf.c
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
@@ -5,6 +5,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/clk.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -113,6 +114,8 @@ struct ddr_pmu {
int irq;
int id;
spinlock_t lock;
+ struct clk *clk_ipg;
+ struct clk *clk_cnt;
};
enum ddr_perf_filter_capabilities {
@@ -300,6 +303,27 @@ static const struct attribute_group *db_attr_groups[] = {
NULL,
};
+static int ddr_perf_clks_enable(struct ddr_pmu *pmu)
+{
+ int err;
+
+ err = clk_prepare_enable(pmu->clk_ipg);
+ if (err)
+ return err;
+
+ err = clk_prepare_enable(pmu->clk_cnt);
+ if (err)
+ clk_disable_unprepare(pmu->clk_ipg);
+
+ return err;
+}
+
+static void ddr_perf_clks_disable(struct ddr_pmu *pmu)
+{
+ clk_disable_unprepare(pmu->clk_cnt);
+ clk_disable_unprepare(pmu->clk_ipg);
+}
+
static bool ddr_perf_is_filtered(struct perf_event *event)
{
return event->attr.config == 0x41 || event->attr.config == 0x42;
@@ -754,6 +778,22 @@ static int ddr_perf_probe(struct platform_device *pdev)
pmu->pmu.attr_groups = db_attr_groups;
pmu->id = ida_simple_get(&db_ida, 0, 0, GFP_KERNEL);
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DB_PERF_DEV_NAME "%d", pmu->id);
+
+ pmu->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(pmu->clk_ipg)) {
+ dev_err(&pdev->dev, "no ipg clock defined\n");
+ return PTR_ERR(pmu->clk_ipg);
+ }
+
+ pmu->clk_cnt = devm_clk_get(&pdev->dev, "cnt");
+ if (IS_ERR(pmu->clk_cnt)) {
+ dev_err(&pdev->dev, "no cnt clock defined\n");
+ return PTR_ERR(pmu->clk_cnt);
+ }
+
+ ret = ddr_perf_clks_enable(pmu);
+ if (ret)
+ return ret;
} else
return -EINVAL;
if (!name)
@@ -812,8 +852,10 @@ ddr_perf_err:
if (pmu->devtype_data->type & DDR_PERF_TYPE)
ida_simple_remove(&ddr_ida, pmu->id);
- else
+ else {
+ ddr_perf_clks_disable(pmu);
ida_simple_remove(&db_ida, pmu->id);
+ }
dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret);
return ret;
@@ -830,8 +872,10 @@ static int ddr_perf_remove(struct platform_device *pdev)
if (pmu->devtype_data->type & DDR_PERF_TYPE)
ida_simple_remove(&ddr_ida, pmu->id);
- else
+ else {
+ ddr_perf_clks_disable(pmu);
ida_simple_remove(&db_ida, pmu->id);
+ }
return 0;
}