* [PATCH RFC 2/2] clk: scmi: Add support for two #clock-cells to pass rate rounding mode
2026-03-06 6:20 [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy) Peng Fan (OSS)
2026-03-06 6:20 ` [PATCH RFC 1/2] dt-bindings: clock: Add SCMI clock rounding mode declarations Peng Fan (OSS)
@ 2026-03-06 6:20 ` Peng Fan (OSS)
2026-04-04 1:53 ` [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy) Peng Fan
2026-04-06 15:38 ` Brian Masney
3 siblings, 0 replies; 5+ messages in thread
From: Peng Fan (OSS) @ 2026-03-06 6:20 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sudeep Holla, Cristian Marussi
Cc: linux-kernel, linux-clk, devicetree, arm-scmi, linux-arm-kernel,
Peng Fan
From: Peng Fan <peng.fan@nxp.com>
SCMI CLOCK_RATE_SET allows the caller to specify the rounding behaviour
when setting a clock rate. The previously added dt-bindings header
defines three modes:
ROUND_DOWN / ROUND_UP / ROUND_AUTO
To enable device tree clients to select a rounding mode, extend the
SCMI clock provider to support "#clock-cells = <2>", where the second
cell encodes the desired rounding mode. The default remains
ROUND_DOWN for backwards compatibility with existing device trees.
When two cells are used, scmi_clk_two_cells_get() extracts the rounding
mode and stores it per clock. The SCMI clk driver then passes this
value to the SCMI Clock protocol, which maps it to the appropriate
CLOCK_SET_* flag.
Existing DTs using "#clock-cells = <1>" are also being supported.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/clk/clk-scmi.c | 62 +++++++++++++++++++++++++++++++++++++--
drivers/firmware/arm_scmi/clock.c | 15 ++++++++--
include/linux/scmi_protocol.h | 8 ++++-
3 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 6b286ea6f1218c802d0ebb782c75a19057581c20..16547a1fa1a0f1595323b0f89753b38315743150 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -5,6 +5,7 @@
* Copyright (C) 2018-2024 ARM Ltd.
*/
+#include <dt-bindings/clock/scmi.h>
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
@@ -32,6 +33,8 @@ static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
struct scmi_clk {
u32 id;
+ u32 round;
+ bool round_set; /* policy latched once */
struct device *dev;
struct clk_hw hw;
const struct scmi_clock_info *info;
@@ -94,8 +97,20 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct scmi_clk *clk = to_scmi_clk(hw);
+ u32 round;
+
+ switch (clk->round) {
+ case ROUND_UP:
+ round = SCMI_CLOCK_ROUND_UP;
+ break;
+ case ROUND_AUTO:
+ round = SCMI_CLOCK_ROUND_AUTO;
+ break;
+ default:
+ round = SCMI_CLOCK_ROUND_DOWN;
+ }
- return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
+ return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, round, rate);
}
static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
@@ -396,6 +411,41 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
return ops;
}
+static struct clk_hw *
+scmi_clk_two_cells_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct clk_hw_onecell_data *hw_data = data;
+ unsigned int idx = clkspec->args[0];
+ u32 round = clkspec->args[1];
+ struct scmi_clk *clk;
+ struct clk_hw *hw;
+
+ if (idx >= hw_data->num) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (round > ROUND_AUTO) {
+ pr_err("%s: invalid round method %u\n", __func__, round);
+ return ERR_PTR(-EINVAL);
+ }
+
+ hw = hw_data->hws[idx];
+ clk = to_scmi_clk(hw);
+
+ /* per-clock policy: latch on first use, refuse conflicts */
+ if (clk->round_set && clk->round != round) {
+ pr_warn("%s: conflicting rounding mode for clk idx %u: %u != %u\n",
+ __func__, idx, clk->round, round);
+ return ERR_PTR(-EINVAL);
+ }
+
+ clk->round = round;
+ clk->round_set = true;
+
+ return hw;
+}
+
static int scmi_clocks_probe(struct scmi_device *sdev)
{
int idx, count, err;
@@ -409,6 +459,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
struct scmi_protocol_handle *ph;
const struct clk_ops *scmi_clk_ops_db[SCMI_MAX_CLK_OPS] = {};
struct scmi_clk *sclks;
+ u32 cells = 1;
if (!handle)
return -ENODEV;
@@ -456,6 +507,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
sclk->id = idx;
sclk->ph = ph;
sclk->dev = dev;
+ sclk->round = ROUND_DOWN;
+ sclk->round_set = false;
/*
* Note that the scmi_clk_ops_db is on the stack, not global,
@@ -495,8 +548,11 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
}
}
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
- clk_data);
+ of_property_read_u32(np, "#clock-cells", &cells);
+ if (cells == 2)
+ return devm_of_clk_add_hw_provider(dev, scmi_clk_two_cells_get, clk_data);
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
}
static const struct scmi_device_id scmi_id_table[] = {
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index ab36871650a1ff890c4cb7f67d3ded2622a72868..1548b6611f7f6c4ac60e740bb36f2377568d06dd 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -570,10 +570,10 @@ scmi_clock_rate_get(const struct scmi_protocol_handle *ph,
}
static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
- u32 clk_id, u64 rate)
+ u32 clk_id, u32 round, u64 rate)
{
int ret;
- u32 flags = 0;
+ u32 flags;
struct scmi_xfer *t;
struct scmi_clock_set_rate *cfg;
struct clock_info *ci = ph->get_priv(ph);
@@ -590,6 +590,17 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
if (ret)
return ret;
+ switch (round) {
+ case SCMI_CLOCK_ROUND_UP:
+ flags = CLOCK_SET_ROUND_UP;
+ break;
+ case SCMI_CLOCK_ROUND_AUTO:
+ flags = CLOCK_SET_ROUND_AUTO;
+ break;
+ default:
+ flags = 0;
+ }
+
if (ci->max_async_req &&
atomic_inc_return(&ci->cur_async_req) < ci->max_async_req)
flags |= CLOCK_SET_ASYNC;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index aafaac1496b06a6e4f0ca32eee58a9edf7d4a70f..d0b7186177f49dea9c4b0030927782e6fd819ad0 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -83,6 +83,12 @@ enum scmi_clock_oem_config {
SCMI_CLOCK_CFG_OEM_END = 0xFF,
};
+enum scmi_clock_round {
+ SCMI_CLOCK_ROUND_DOWN = 0x0,
+ SCMI_CLOCK_ROUND_UP = 0x1,
+ SCMI_CLOCK_ROUND_AUTO = 0x2,
+};
+
/**
* struct scmi_clk_proto_ops - represents the various operations provided
* by SCMI Clock Protocol
@@ -107,7 +113,7 @@ struct scmi_clk_proto_ops {
int (*rate_get)(const struct scmi_protocol_handle *ph, u32 clk_id,
u64 *rate);
int (*rate_set)(const struct scmi_protocol_handle *ph, u32 clk_id,
- u64 rate);
+ u32 round, u64 rate);
int (*enable)(const struct scmi_protocol_handle *ph, u32 clk_id,
bool atomic);
int (*disable)(const struct scmi_protocol_handle *ph, u32 clk_id,
--
2.37.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy)
2026-03-06 6:20 [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy) Peng Fan (OSS)
2026-03-06 6:20 ` [PATCH RFC 1/2] dt-bindings: clock: Add SCMI clock rounding mode declarations Peng Fan (OSS)
2026-03-06 6:20 ` [PATCH RFC 2/2] clk: scmi: Add support for two #clock-cells to pass rate rounding mode Peng Fan (OSS)
@ 2026-04-04 1:53 ` Peng Fan
2026-04-06 15:38 ` Brian Masney
3 siblings, 0 replies; 5+ messages in thread
From: Peng Fan @ 2026-04-04 1:53 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sudeep Holla, Cristian Marussi, Brian Masney
Cc: linux-kernel, linux-clk, devicetree, arm-scmi, linux-arm-kernel,
Peng Fan
Hi All,
On Fri, Mar 06, 2026 at 02:20:11PM +0800, Peng Fan (OSS) wrote:
>The ARM SCMI specification (DEN0056E) defines rounding‑mode flags for the
>CLOCK_RATE_SET command, allowing a client to request that the firmware
>round a requested clock rate down, up, or autonomously choose the
>closest achievable rate.
Would you please give a look and give some feedback?
Thanks,
Peng
>This series introduces DT support in the SCMI clock provider to carry a
>per‑clock rounding policy from the device tree into the SCMI protocol.
>
>Patch 1 adds dt‑bindings constants for rounding modes:
>ROUND_DOWN, ROUND_UP, ROUND_AUTO.
>
>Patch 2 extends the SCMI clock provider to optionally support
>"#clock-cells = <2>", where the second cell encodes the rounding mode.
>The first consumer that references a given clock latches the per‑clock
>policy. Subsequent consumers of the same clock must specify the same
>mode; otherwise, the request is rejected to avoid non‑deterministic
>behavior. The selected mode is passed through to the SCMI Clock protocol
>and mapped to the corresponding CLOCK_SET_* flag.
>
>Patch 2 includes changes to drivers/clk/clk-scmi.c and drivers/firmware
>arm_scmi/clock.c, it is hard to separate the changes without breaking,
>so I put the changes in one patch.
>
>This design adopts a per‑clock policy model, not per‑consumer. The rounding
>mode is applied by the provider per clock (index).
>All consumers of the same clock must agree on the rounding mode.
>Conflicting per‑consumer requests for the same clock are invalid and
>are rejected during phandle translation.
>
>This avoids silent clobbering and preserves deterministic behavior.
>
>Existing device trees using #clock-cells = <1> continue to work and
>default to ROUND_DOWN, exactly as before.
>
>Signed-off-by: Peng Fan <peng.fan@nxp.com>
>---
>Peng Fan (2):
> dt-bindings: clock: Add SCMI clock rounding mode declarations
> clk: scmi: Add support for two #clock-cells to pass rate rounding mode
>
> drivers/clk/clk-scmi.c | 62 +++++++++++++++++++++++++++++++++++++--
> drivers/firmware/arm_scmi/clock.c | 15 ++++++++--
> include/dt-bindings/clock/scmi.h | 13 ++++++++
> include/linux/scmi_protocol.h | 8 ++++-
> 4 files changed, 92 insertions(+), 6 deletions(-)
>---
>base-commit: 3f9cd19e764b782706dbaacc69e502099cb014ba
>change-id: 20260306-scmi-clk-round-1615258cf0fa
>
>Best regards,
>--
>Peng Fan <peng.fan@nxp.com>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy)
2026-03-06 6:20 [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy) Peng Fan (OSS)
` (2 preceding siblings ...)
2026-04-04 1:53 ` [PATCH RFC 0/2] clk: scmi: DT support for SCMI clock rate rounding modes (per‑clock policy) Peng Fan
@ 2026-04-06 15:38 ` Brian Masney
3 siblings, 0 replies; 5+ messages in thread
From: Brian Masney @ 2026-04-06 15:38 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sudeep Holla, Cristian Marussi, linux-kernel,
linux-clk, devicetree, arm-scmi, linux-arm-kernel, Peng Fan
Hi Peng,
On Fri, Mar 06, 2026 at 02:20:11PM +0800, Peng Fan (OSS) wrote:
> The ARM SCMI specification (DEN0056E) defines rounding‑mode flags for the
> CLOCK_RATE_SET command, allowing a client to request that the firmware
> round a requested clock rate down, up, or autonomously choose the
> closest achievable rate.
> This series introduces DT support in the SCMI clock provider to carry a
> per‑clock rounding policy from the device tree into the SCMI protocol.
>
> Patch 1 adds dt‑bindings constants for rounding modes:
> ROUND_DOWN, ROUND_UP, ROUND_AUTO.
>
> Patch 2 extends the SCMI clock provider to optionally support
> "#clock-cells = <2>", where the second cell encodes the rounding mode.
> The first consumer that references a given clock latches the per‑clock
> policy. Subsequent consumers of the same clock must specify the same
> mode; otherwise, the request is rejected to avoid non‑deterministic
> behavior. The selected mode is passed through to the SCMI Clock protocol
> and mapped to the corresponding CLOCK_SET_* flag.
>
> Patch 2 includes changes to drivers/clk/clk-scmi.c and drivers/firmware
> arm_scmi/clock.c, it is hard to separate the changes without breaking,
> so I put the changes in one patch.
>
> This design adopts a per‑clock policy model, not per‑consumer. The rounding
> mode is applied by the provider per clock (index).
> All consumers of the same clock must agree on the rounding mode.
> Conflicting per‑consumer requests for the same clock are invalid and
> are rejected during phandle translation.
>
> This avoids silent clobbering and preserves deterministic behavior.
>
> Existing device trees using #clock-cells = <1> continue to work and
> default to ROUND_DOWN, exactly as before.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
My high level feedback about this:
1) Since you are making changes to the DT schema for the clock-cells,
does the SCMI DT schema document also need to be updated to allow
clock-cells to be 1 or 2?
2) For the ROUND_XXX constants, I would prefix them with something
since the existing ROUND names are fairly generic sounding. Maybe
CLK_SCMI_?
Brian
^ permalink raw reply [flat|nested] 5+ messages in thread