From: Sebastian Reichel <sebastian.reichel@collabora.com>
To: Stephen Boyd <sboyd@kernel.org>,
Brian Masney <bmasney+clk@redhat.com>,
Jerome Brunet <jbrunet+clk@baylibre.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Heiko Stuebner <heiko@sntech.de>,
Chanwoo Choi <cw00.choi@samsung.com>,
MyungJoo Ham <myungjoo.ham@samsung.com>,
Kyungmin Park <kyungmin.park@samsung.com>,
Sascha Hauer <s.hauer@pengutronix.de>
Cc: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>,
linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,
kernel@collabora.com,
Sebastian Reichel <sebastian.reichel@collabora.com>
Subject: [PATCH 3/8] PM / devfreq: rockchip-dfi: move to per-variant const structs
Date: Thu, 17 Sep 2026 15:49:15 +0200 [thread overview]
Message-ID: <20260917-rockchip-dfi-cleanup-v1-3-4f00a97a69a6@collabora.com> (raw)
In-Reply-To: <20260917-rockchip-dfi-cleanup-v1-0-4f00a97a69a6@collabora.com>
From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
The rockchip-dfi driver supports several variants of the DDR monitoring
hardware. The differences in these variants are handled with one init
function for each variant.
However, some of the members that these init functions set are actually
constants, specific to that variant, with no runtime involvement from
reading registers or anything.
Refactor the code to move those values (and the soc_init function
pointer) into a new struct. Declare some const instances of this variant
struct, and use it wherever needed.
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
drivers/devfreq/event/rockchip-dfi.c | 94 +++++++++++++++++++++---------------
1 file changed, 54 insertions(+), 40 deletions(-)
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 255aee1bdd91..5339616f7ca6 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -103,7 +103,6 @@ struct rockchip_dfi {
struct mutex mutex;
u32 ddr_type;
unsigned int channel_mask;
- unsigned int max_channels;
enum cpuhp_state cpuhp_state;
struct hlist_node node;
struct pmu pmu;
@@ -112,11 +111,17 @@ struct rockchip_dfi {
int active_events;
int burst_len;
int buswidth[DMC_MAX_CHANNELS];
- int ddrmon_stride;
- bool ddrmon_ctrl_single;
u32 lp5_bank_mode;
bool lp5_ckr; /* true if in 4:1 command-to-data clock ratio mode */
unsigned int count_multiplier; /* number of data clocks per count */
+ const struct rockchip_dfi_variant *variant;
+};
+
+struct rockchip_dfi_variant {
+ int (*init)(struct rockchip_dfi *dfi);
+ int stride;
+ bool ctrl_single;
+ unsigned int max_channels;
};
static int rockchip_dfi_ddrtype_to_ctrl(struct rockchip_dfi *dfi, u32 *ctrl)
@@ -188,7 +193,7 @@ static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
if (ret)
goto out;
- for (i = 0; i < dfi->max_channels; i++) {
+ for (i = 0; i < dfi->variant->max_channels; i++) {
if (!(dfi->channel_mask & BIT(i)))
continue;
@@ -197,16 +202,16 @@ static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
writel_relaxed(FIELD_PREP_WM16(DDRMON_CTRL_TIMER_CNT_EN, 0) |
FIELD_PREP_WM16(DDRMON_CTRL_SOFTWARE_EN, 0) |
FIELD_PREP_WM16(DDRMON_CTRL_HARDWARE_EN, 0),
- dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+ dfi_regs + i * dfi->variant->stride + DDRMON_CTRL);
- writel_relaxed(ctrl, dfi_regs + i * dfi->ddrmon_stride +
+ writel_relaxed(ctrl, dfi_regs + i * dfi->variant->stride +
DDRMON_CTRL);
/* enable count, use software mode */
writel_relaxed(FIELD_PREP_WM16(DDRMON_CTRL_SOFTWARE_EN, 1),
- dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+ dfi_regs + i * dfi->variant->stride + DDRMON_CTRL);
- if (dfi->ddrmon_ctrl_single)
+ if (dfi->variant->ctrl_single)
break;
}
out:
@@ -229,14 +234,14 @@ static void rockchip_dfi_disable(struct rockchip_dfi *dfi)
if (dfi->usecount > 0)
goto out;
- for (i = 0; i < dfi->max_channels; i++) {
+ for (i = 0; i < dfi->variant->max_channels; i++) {
if (!(dfi->channel_mask & BIT(i)))
continue;
writel_relaxed(FIELD_PREP_WM16(DDRMON_CTRL_SOFTWARE_EN, 0),
- dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
+ dfi_regs + i * dfi->variant->stride + DDRMON_CTRL);
- if (dfi->ddrmon_ctrl_single)
+ if (dfi->variant->ctrl_single)
break;
}
@@ -250,17 +255,17 @@ static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_coun
u32 i;
void __iomem *dfi_regs = dfi->regs;
- for (i = 0; i < dfi->max_channels; i++) {
+ for (i = 0; i < dfi->variant->max_channels; i++) {
if (!(dfi->channel_mask & BIT(i)))
continue;
res->c[i].read_access = readl_relaxed(dfi_regs +
- DDRMON_CH0_RD_NUM + i * dfi->ddrmon_stride);
+ DDRMON_CH0_RD_NUM + i * dfi->variant->stride);
res->c[i].write_access = readl_relaxed(dfi_regs +
- DDRMON_CH0_WR_NUM + i * dfi->ddrmon_stride);
+ DDRMON_CH0_WR_NUM + i * dfi->variant->stride);
res->c[i].access = readl_relaxed(dfi_regs +
- DDRMON_CH0_DFI_ACCESS_NUM + i * dfi->ddrmon_stride);
+ DDRMON_CH0_DFI_ACCESS_NUM + i * dfi->variant->stride);
res->c[i].clock_cycles = readl_relaxed(dfi_regs +
- DDRMON_CH0_COUNT_NUM + i * dfi->ddrmon_stride);
+ DDRMON_CH0_COUNT_NUM + i * dfi->variant->stride);
}
}
@@ -297,7 +302,7 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
rockchip_dfi_read_counters(dfi, &count);
/* We can only report one channel, so find the busiest one */
- for (i = 0; i < dfi->max_channels; i++) {
+ for (i = 0; i < dfi->variant->max_channels; i++) {
u32 a, c;
if (!(dfi->channel_mask & BIT(i)))
@@ -336,7 +341,7 @@ static void rockchip_ddr_perf_counters_add(struct rockchip_dfi *dfi,
const struct dmc_count *last = &dfi->last_perf_count;
int i;
- for (i = 0; i < dfi->max_channels; i++) {
+ for (i = 0; i < dfi->variant->max_channels; i++) {
res->c[i].read_access = dfi->total_count.c[i].read_access +
(u32)(now->c[i].read_access - last->c[i].read_access);
res->c[i].write_access = dfi->total_count.c[i].write_access +
@@ -477,11 +482,11 @@ static u64 rockchip_ddr_perf_event_get_count(struct perf_event *event)
count = total.c[0].clock_cycles * dfi->count_multiplier;
break;
case PERF_EVENT_READ_BYTES:
- for (i = 0; i < dfi->max_channels; i++)
+ for (i = 0; i < dfi->variant->max_channels; i++)
count += total.c[i].read_access * blen * dfi->buswidth[i];
break;
case PERF_EVENT_WRITE_BYTES:
- for (i = 0; i < dfi->max_channels; i++)
+ for (i = 0; i < dfi->variant->max_channels; i++)
count += total.c[i].write_access * blen * dfi->buswidth[i];
break;
case PERF_EVENT_READ_BYTES0:
@@ -509,7 +514,7 @@ static u64 rockchip_ddr_perf_event_get_count(struct perf_event *event)
count = total.c[3].write_access * blen * dfi->buswidth[3];
break;
case PERF_EVENT_BYTES:
- for (i = 0; i < dfi->max_channels; i++)
+ for (i = 0; i < dfi->variant->max_channels; i++)
count += total.c[i].access * blen * dfi->buswidth[i];
break;
}
@@ -726,14 +731,10 @@ static int rk3399_dfi_init(struct rockchip_dfi *dfi)
dfi->ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val);
dfi->channel_mask = GENMASK(1, 0);
- dfi->max_channels = 2;
dfi->buswidth[0] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH0, val) == 0 ? 4 : 2;
dfi->buswidth[1] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH1, val) == 0 ? 4 : 2;
- dfi->ddrmon_stride = 0x14;
- dfi->ddrmon_ctrl_single = true;
-
return 0;
};
@@ -756,13 +757,9 @@ static int rk3568_dfi_init(struct rockchip_dfi *dfi)
dfi->ddr_type |= FIELD_GET(RK3568_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3;
dfi->channel_mask = BIT(0);
- dfi->max_channels = 1;
dfi->buswidth[0] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2;
- dfi->ddrmon_stride = 0x0; /* not relevant, we only have a single channel on this SoC */
- dfi->ddrmon_ctrl_single = true;
-
return 0;
};
@@ -791,9 +788,7 @@ static int rk3588_dfi_init(struct rockchip_dfi *dfi)
dfi->buswidth[3] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg4) == 0 ? 4 : 2;
dfi->channel_mask = FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg2) |
FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg4) << 2;
- dfi->max_channels = 4;
- dfi->ddrmon_stride = 0x4000;
dfi->count_multiplier = 2;
if (dfi->ddr_type == ROCKCHIP_DDRTYPE_LPDDR5) {
@@ -807,10 +802,30 @@ static int rk3588_dfi_init(struct rockchip_dfi *dfi)
return 0;
};
+static const struct rockchip_dfi_variant rk3399_variant = {
+ .init = rk3399_dfi_init,
+ .stride = 0x14,
+ .ctrl_single = true,
+ .max_channels = 2,
+};
+
+static const struct rockchip_dfi_variant rk3568_variant = {
+ .init = rk3568_dfi_init,
+ .stride = 0x0,
+ .ctrl_single = true,
+ .max_channels = 1,
+};
+
+static const struct rockchip_dfi_variant rk3588_variant = {
+ .init = rk3588_dfi_init,
+ .stride = 0x4000,
+ .max_channels = 4,
+};
+
static const struct of_device_id rockchip_dfi_id_match[] = {
- { .compatible = "rockchip,rk3399-dfi", .data = rk3399_dfi_init },
- { .compatible = "rockchip,rk3568-dfi", .data = rk3568_dfi_init },
- { .compatible = "rockchip,rk3588-dfi", .data = rk3588_dfi_init },
+ { .compatible = "rockchip,rk3399-dfi", .data = &rk3399_variant },
+ { .compatible = "rockchip,rk3568-dfi", .data = &rk3568_variant },
+ { .compatible = "rockchip,rk3588-dfi", .data = &rk3588_variant },
{ },
};
@@ -822,17 +837,16 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
struct rockchip_dfi *dfi;
struct devfreq_event_desc *desc;
struct device_node *np = pdev->dev.of_node, *node;
- int (*soc_init)(struct rockchip_dfi *dfi);
int ret;
- soc_init = of_device_get_match_data(&pdev->dev);
- if (!soc_init)
- return -EINVAL;
-
dfi = devm_kzalloc(dev, sizeof(*dfi), GFP_KERNEL);
if (!dfi)
return -ENOMEM;
+ dfi->variant = of_device_get_match_data(dev);
+ if (!dfi->variant)
+ return -EINVAL;
+
dfi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dfi->regs))
return PTR_ERR(dfi->regs);
@@ -854,7 +868,7 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
desc->driver_data = dfi;
desc->name = np->name;
- ret = soc_init(dfi);
+ ret = dfi->variant->init(dfi);
if (ret)
return ret;
--
2.53.0
next prev parent reply other threads:[~2026-09-17 13:49 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-17 13:49 [PATCH 0/8] PM / devfreq: rockchip-dfi: cleanups Sebastian Reichel
2026-09-17 13:49 ` [PATCH 1/8] dt-bindings: clock: rk3588: add PCLK_DDR_MON_CH clocks Sebastian Reichel
2026-09-17 13:49 ` [PATCH 2/8] dt-bindings: devfreq: event: rockchip,dfi: add clocks to rk3588 Sebastian Reichel
2026-09-17 13:49 ` Sebastian Reichel [this message]
2026-09-17 13:49 ` [PATCH 4/8] PM / devfreq: rockchip-dfi: add NO_INTERRUPT perf capability Sebastian Reichel
2026-09-17 13:49 ` [PATCH 5/8] PM / devfreq: rockchip-dfi: use bulk clock APIs Sebastian Reichel
2026-09-17 13:49 ` [PATCH 6/8] clk: rockchip: rk3588: add PCLK_DDR_MON_CH gate branches Sebastian Reichel
2026-09-17 13:49 ` [PATCH 7/8] PM / devfreq: rockchip-dfi: make RK3588 use its clocks Sebastian Reichel
2026-09-17 13:49 ` [PATCH 8/8] arm64: dts: rockchip: add dfi clocks on RK3588 Sebastian Reichel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260917-rockchip-dfi-cleanup-v1-3-4f00a97a69a6@collabora.com \
--to=sebastian.reichel@collabora.com \
--cc=bmasney+clk@redhat.com \
--cc=conor+dt@kernel.org \
--cc=cw00.choi@samsung.com \
--cc=devicetree@vger.kernel.org \
--cc=heiko@sntech.de \
--cc=jbrunet+clk@baylibre.com \
--cc=kernel@collabora.com \
--cc=krzk+dt@kernel.org \
--cc=kyungmin.park@samsung.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=myungjoo.ham@samsung.com \
--cc=nicolas.frattaroli@collabora.com \
--cc=robh@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=sboyd@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®