Commit d724f4a4 authored by Sascha Hauer's avatar Sascha Hauer Committed by Chanwoo Choi
Browse files

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: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Acked-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent b82932fb
Loading
Loading
Loading
Loading
+40 −17
Original line number Diff line number Diff line
@@ -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;