[PATCH v2 01/12] clk: add new flag CLK_ROUNDING_NOOP

From: Brian Masney

Date: Mon Mar 09 2026 - 10:42:14 EST


There are some clocks where the determine_rate clk op is just an empty
function that returns 0. This can be either because the rounding is
managed by the firmware, or the clock is capable of any rate. Add a
new flag for these type of clocks, and update the clk core so that the
determine_rate() clk op is not required when this flag is set.

Acked-by: Sudeep Holla <sudeep.holla@xxxxxxxxxx>
Signed-off-by: Brian Masney <bmasney@xxxxxxxxxx>
---
To: Michael Turquette <mturquette@xxxxxxxxxxxx>
To: Stephen Boyd <sboyd@xxxxxxxxxx>
To: Abel Vesa <abelvesa@xxxxxxxxxx>
To: Andrea della Porta <andrea.porta@xxxxxxxx>
To: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx>
To: Bjorn Andersson <andersson@xxxxxxxxxx>
To: Chanwoo Choi <cw00.choi@xxxxxxxxxxx>
To: Frank Li <Frank.Li@xxxxxxx>
To: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
To: Krzysztof Kozlowski <krzk@xxxxxxxxxx>
To: Orson Zhai <orsonzhai@xxxxxxxxx>
To: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
To: Sudeep Holla <sudeep.holla@xxxxxxxxxx>
To: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>
To: Tudor Ambarus <tudor.ambarus@xxxxxxxxxx>
Cc: linux-clk@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Cc: Alim Akhtar <alim.akhtar@xxxxxxxxxxx>
Cc: arm-scmi@xxxxxxxxxxxxxxx
Cc: Chunyan Zhang <zhang.lyra@xxxxxxxxx>
Cc: Cristian Marussi <cristian.marussi@xxxxxxx>
Cc: Fabio Estevam <festevam@xxxxxxxxx>
Cc: imx@xxxxxxxxxxxxxxx
Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
Cc: linux-arm-msm@xxxxxxxxxxxxxxx
Cc: linux-renesas-soc@xxxxxxxxxxxxxxx
Cc: linux-samsung-soc@xxxxxxxxxxxxxxx
Cc: Peng Fan <peng.fan@xxxxxxx>
Cc: Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>
---
drivers/clk/clk.c | 31 ++++++++++++++++++++++++++++---
include/linux/clk-provider.h | 2 ++
2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fd418dc988b1c60c49e3ac9c0c44aa132dd5da28..1187e5b1dbc123d2d2c1f43690d7dcf75a7c4ac3 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1557,6 +1557,21 @@ static int __init clk_disable_unused(void)
}
late_initcall_sync(clk_disable_unused);

+/**
+ * clk_is_rounding_noop - Check to see if noop clk rounding is used.
+ *
+ * @core: the clk to check
+ *
+ * Clks that have this flag enabled do not need to have a determine_rate() op
+ * set, and will always return success for any rounding operation. This can be
+ * either because the rounding is managed by the firmware, or the clock is
+ * capable of any rate.
+ */
+static inline bool clk_is_rounding_noop(struct clk_core *core)
+{
+ return core->flags & CLK_ROUNDING_NOOP;
+}
+
static int clk_core_determine_round_nolock(struct clk_core *core,
struct clk_rate_request *req)
{
@@ -1589,6 +1604,8 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
req->rate = core->rate;
} else if (core->ops->determine_rate) {
return core->ops->determine_rate(core->hw, req);
+ } else if (clk_is_rounding_noop(core)) {
+ return 0;
} else {
return -EINVAL;
}
@@ -1673,7 +1690,7 @@ EXPORT_SYMBOL_GPL(clk_hw_forward_rate_request);

static bool clk_core_can_round(struct clk_core * const core)
{
- return core->ops->determine_rate;
+ return core->ops->determine_rate || clk_is_rounding_noop(core);
}

static int clk_core_round_rate_nolock(struct clk_core *core,
@@ -3528,6 +3545,7 @@ static const struct {
ENTRY(CLK_IS_CRITICAL),
ENTRY(CLK_OPS_PARENT_ENABLE),
ENTRY(CLK_DUTY_CYCLE_PARENT),
+ ENTRY(CLK_ROUNDING_NOOP),
#undef ENTRY
};

@@ -3906,13 +3924,19 @@ static int __clk_core_init(struct clk_core *core)

/* check that clk_ops are sane. See Documentation/driver-api/clk.rst */
if (core->ops->set_rate && !core->ops->determine_rate &&
- core->ops->recalc_rate) {
+ core->ops->recalc_rate && !clk_is_rounding_noop(core)) {
pr_err("%s: %s must implement .determine_rate in addition to .recalc_rate\n",
__func__, core->name);
ret = -EINVAL;
goto out;
}

+ if (clk_is_rounding_noop(core) && core->ops->determine_rate) {
+ pr_err("%s: %s cannot implement both .determine_rate and CLK_ROUNDING_NOOP\n",
+ __func__, core->name);
+ goto out;
+ }
+
if (core->ops->set_parent && !core->ops->get_parent) {
pr_err("%s: %s must implement .get_parent & .set_parent\n",
__func__, core->name);
@@ -3920,7 +3944,8 @@ static int __clk_core_init(struct clk_core *core)
goto out;
}

- if (core->ops->set_parent && !core->ops->determine_rate) {
+ if (core->ops->set_parent && !core->ops->determine_rate &&
+ !clk_is_rounding_noop(core)) {
pr_err("%s: %s must implement .set_parent & .determine_rate\n",
__func__, core->name);
ret = -EINVAL;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1cda2c78dffaff037f0f16b0f11106b63b3a746f..33afef9403b526976af80881461bbfe1e4b76c77 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -32,6 +32,8 @@
#define CLK_OPS_PARENT_ENABLE BIT(12)
/* duty cycle call may be forwarded to the parent clock */
#define CLK_DUTY_CYCLE_PARENT BIT(13)
+/* clock rate rounding is managed by firmware, don't require determine_rate */
+#define CLK_ROUNDING_NOOP BIT(14)

struct clk;
struct clk_hw;

--
2.53.0