summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2023-10-18 08:17:02 +0200
committerChanwoo Choi <cw00.choi@samsung.com>2023-10-19 13:50:10 +0200
commitd724f4a4581b2910ce79b45bd353ee66e7cf9d7f (patch)
tree7c2d36abf97329b59c8fbf566b5cc95fccb5d417 /drivers/devfreq
parentPM / devfreq: rockchip-dfi: Pass private data struct to internal functions (diff)
downloadlinux-d724f4a4581b2910ce79b45bd353ee66e7cf9d7f.tar.xz
linux-d724f4a4581b2910ce79b45bd353ee66e7cf9d7f.zip
PM / devfreq: rockchip-dfi: Prepare for multiple users
When adding perf support later the DFI must be enabled when either of devfreq-event or perf is active. Prepare for that by adding a usage counter for the DFI. Also move enabling and disabling of the clock away from the devfreq-event specific functions to which the perf specific part won't have access. Link: https://lore.kernel.org/all/20231018061714.3553817-15-s.hauer@pengutronix.de/ Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/event/rockchip-dfi.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index d56a33d03db4..7a4f1901314d 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -68,14 +68,29 @@ struct rockchip_dfi {
void __iomem *regs;
struct regmap *regmap_pmu;
struct clk *clk;
+ int usecount;
+ struct mutex mutex;
u32 ddr_type;
unsigned int channel_mask;
unsigned int max_channels;
};
-static void rockchip_dfi_start_hardware_counter(struct rockchip_dfi *dfi)
+static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
{
void __iomem *dfi_regs = dfi->regs;
+ int ret = 0;
+
+ mutex_lock(&dfi->mutex);
+
+ dfi->usecount++;
+ if (dfi->usecount > 1)
+ goto out;
+
+ ret = clk_prepare_enable(dfi->clk);
+ if (ret) {
+ dev_err(&dfi->edev->dev, "failed to enable dfi clk: %d\n", ret);
+ goto out;
+ }
/* clear DDRMON_CTRL setting */
writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_TIMER_CNT_EN | DDRMON_CTRL_SOFTWARE_EN |
@@ -100,14 +115,30 @@ static void rockchip_dfi_start_hardware_counter(struct rockchip_dfi *dfi)
/* enable count, use software mode */
writel_relaxed(HIWORD_UPDATE(DDRMON_CTRL_SOFTWARE_EN, DDRMON_CTRL_SOFTWARE_EN),
dfi_regs + DDRMON_CTRL);
+out:
+ mutex_unlock(&dfi->mutex);
+
+ return ret;
}
-static void rockchip_dfi_stop_hardware_counter(struct rockchip_dfi *dfi)
+static void rockchip_dfi_disable(struct rockchip_dfi *dfi)
{
void __iomem *dfi_regs = dfi->regs;
+ mutex_lock(&dfi->mutex);
+
+ dfi->usecount--;
+
+ WARN_ON_ONCE(dfi->usecount < 0);
+
+ if (dfi->usecount > 0)
+ goto out;
+
writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_SOFTWARE_EN),
dfi_regs + DDRMON_CTRL);
+ clk_disable_unprepare(dfi->clk);
+out:
+ mutex_unlock(&dfi->mutex);
}
static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_count *count)
@@ -125,29 +156,20 @@ static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_coun
}
}
-static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
+static int rockchip_dfi_event_disable(struct devfreq_event_dev *edev)
{
struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
- rockchip_dfi_stop_hardware_counter(dfi);
- clk_disable_unprepare(dfi->clk);
+ rockchip_dfi_disable(dfi);
return 0;
}
-static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
+static int rockchip_dfi_event_enable(struct devfreq_event_dev *edev)
{
struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
- int ret;
-
- ret = clk_prepare_enable(dfi->clk);
- if (ret) {
- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
- return ret;
- }
- rockchip_dfi_start_hardware_counter(dfi);
- return 0;
+ return rockchip_dfi_enable(dfi);
}
static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
@@ -191,8 +213,8 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
}
static const struct devfreq_event_ops rockchip_dfi_ops = {
- .disable = rockchip_dfi_disable,
- .enable = rockchip_dfi_enable,
+ .disable = rockchip_dfi_event_disable,
+ .enable = rockchip_dfi_event_enable,
.get_event = rockchip_dfi_get_event,
.set_event = rockchip_dfi_set_event,
};
@@ -280,6 +302,7 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
return PTR_ERR(dfi->regmap_pmu);
dfi->dev = dev;
+ mutex_init(&dfi->mutex);
desc = &dfi->desc;
desc->ops = &rockchip_dfi_ops;