diff options
author | Joakim Zhang <qiangqing.zhang@nxp.com> | 2020-02-27 17:23:49 +0800 |
---|---|---|
committer | Joakim Zhang <qiangqing.zhang@nxp.com> | 2020-03-04 09:06:04 +0800 |
commit | 3ed9ecdd13bad3b17244e501f5c7af219bbdee54 (patch) | |
tree | d7095517444debcad3697f71ee868a623d72ae64 /drivers/perf | |
parent | 6c8278b52ab6c03198b9c29c705d28e933305aa0 (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.c | 48 |
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; } |