From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F2F413F074C; Fri, 27 Feb 2026 15:33:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206386; cv=none; b=qhglad3Zi1+4SGitjl5pPl09zFPNISVz0VBkq2gbYbEn4F4r7mDV7e2rjzmf5Lxi/6S7MrJfSvRsymGIg+ut56i7x36XPuc33znrA28Qrk8W2dl08aKCSli8fwXNDOXulv+EhUHU4k8b8OCVp7U8QMTAwxWL9/YdFpmSJr8MG9s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206386; c=relaxed/simple; bh=CN8c4/9USCmVuLCHdmKnafZJhuVjmEI7m47N19uUl7w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Wh7bwDdWLd3hWgtbfeMCA19vXH4XG2ocsMUZxxUq95e/pUpypaWMFGXuDUab0+ew39/JcjPYyNWaxv9RXjZiYGApuCtZARdIv5F5SdI5fyrdUMns+MT00qPcfnZDCdH/0MidDkkKKl4/VAs53m0Pf4d2QOStXu2FvUXDl43g4QA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 30D68339; Fri, 27 Feb 2026 07:32:58 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AC71D3F73B; Fri, 27 Feb 2026 07:32:58 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 01/11] firmware: arm_scmi: Add clock determine_rate operation Date: Fri, 27 Feb 2026 15:32:15 +0000 Message-ID: <20260227153225.2778358-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a clock operation to help determining the effective rate, closest to the required one, that a specific clock can support. Calculation is currently performed kernel side and the logic is taken directly from the SCMI Clock driver: embedding the determinate rate logic in the protocol layer enables semplifications in the SCMI Clock protocol interface and will more easily accommodate further evolutions where such determine_rate logic into is optionally delegated to the platform SCMI server. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- Spoiler alert next SCMI spec will most probably include a new CLOCK_DETERMINE_RATE command to delegate to the platform such calculations, so this clock proto_ops will be needed anyway sooner or later --- drivers/firmware/arm_scmi/clock.c | 42 +++++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 6 +++++ 2 files changed, 48 insertions(+) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index ab36871650a1..54e8b59c3941 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -8,6 +8,7 @@ #include #include #include +#include =20 #include "protocols.h" #include "notify.h" @@ -624,6 +625,46 @@ static int scmi_clock_rate_set(const struct scmi_proto= col_handle *ph, return ret; } =20 +static int scmi_clock_determine_rate(const struct scmi_protocol_handle *ph, + u32 clk_id, unsigned long *rate) +{ + u64 fmin, fmax, ftmp; + struct scmi_clock_info *clk; + struct clock_info *ci =3D ph->get_priv(ph); + + if (!rate) + return -EINVAL; + + clk =3D scmi_clock_domain_lookup(ci, clk_id); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* + * If we can't figure out what rate it will be, so just return the + * rate back to the caller. + */ + if (clk->rate_discrete) + return 0; + + fmin =3D clk->range.min_rate; + fmax =3D clk->range.max_rate; + if (*rate <=3D fmin) { + *rate =3D fmin; + return 0; + } else if (*rate >=3D fmax) { + *rate =3D fmax; + return 0; + } + + ftmp =3D *rate - fmin; + ftmp +=3D clk->range.step_size - 1; /* to round up */ + do_div(ftmp, clk->range.step_size); + + *rate =3D ftmp * clk->range.step_size + fmin; + + return 0; +} + static int scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, enum clk_state state, @@ -936,6 +977,7 @@ static const struct scmi_clk_proto_ops clk_proto_ops = =3D { .info_get =3D scmi_clock_info_get, .rate_get =3D scmi_clock_rate_get, .rate_set =3D scmi_clock_rate_set, + .determine_rate =3D scmi_clock_determine_rate, .enable =3D scmi_clock_enable, .disable =3D scmi_clock_disable, .state_get =3D scmi_clock_state_get, diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index aafaac1496b0..28579c145045 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -91,6 +91,10 @@ enum scmi_clock_oem_config { * @info_get: get the information of the specified clock * @rate_get: request the current clock rate of a clock * @rate_set: set the clock rate of a clock + * @determine_rate: determine the effective rate that can be supported by a + * clock calculating the closest allowed rate. + * Note that @rate is an input/output parameter used both to + * describe the requested rate and report the closest match * @enable: enables the specified clock * @disable: disables the specified clock * @state_get: get the status of the specified clock @@ -108,6 +112,8 @@ struct scmi_clk_proto_ops { u64 *rate); int (*rate_set)(const struct scmi_protocol_handle *ph, u32 clk_id, u64 rate); + int (*determine_rate)(const struct scmi_protocol_handle *ph, u32 clk_id, + unsigned long *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, --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0115332825D; Fri, 27 Feb 2026 15:33:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206395; cv=none; b=iODbvWEqHtN4XrfBO095wmA2XWm0CUKUr8r2r02hWKTjQ368ncO4DYVJfALhfaPgbuF0NexszRkSaFcvD2mGJgnjvECQw6DN49RNcR6pkAvUQveLVUVpM0hPvrpmHU87Fv1Woz+6LpEYTWcQB/4E45pDmVkz98sHtcD9x8n0rSk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206395; c=relaxed/simple; bh=x2tqIvC+KFWMvTk4li7/tvcx1v6T+4qmV7LkH248EbI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CnejXu6sdmp2tu/MKow9a0bLRXJ/SmAvq1Rcu5sEVOV/+aVf6K2sywU1qhLrD+ekOG0WBqYP7FWehJouVJWF8s6/rXO+QVI1juyboAKkFMr8fJkoToZn8ZlLRw6y1alM50WApvpiRR0kG8Ry6fxqPiijuAcpjuAGr/yjFV19gCs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 114D5339; Fri, 27 Feb 2026 07:33:07 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1C1593F73B; Fri, 27 Feb 2026 07:33:04 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi , Brian Masney , Michael Turquette , Stephen Boyd Subject: [PATCH 02/11] clk: scmi: Use new determine_rate clock operation Date: Fri, 27 Feb 2026 15:32:16 +0000 Message-ID: <20260227153225.2778358-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use the Clock protocol layer determine_rate logic to calculate the closest rate that can be supported by a specific clock. No functional change. Cc: Brian Masney Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Reviewed-by: Peng Fan Tested-by: Geert Uytterhoeven --- Note that the calculation logic in the protocol layer is exactly the same as it wes here. @Brian I suppose once your CLK_ROUNDING_FW_MANAGED sereis is merged I can f= lag such SCMI clocks. --- drivers/clk/clk-scmi.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index 6b286ea6f121..c223e4ef1dd1 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -12,7 +12,6 @@ #include #include #include -#include =20 #define NOT_ATOMIC false #define ATOMIC true @@ -57,35 +56,17 @@ static unsigned long scmi_clk_recalc_rate(struct clk_hw= *hw, static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - u64 fmin, fmax, ftmp; + int ret; struct scmi_clk *clk =3D to_scmi_clk(hw); =20 /* - * We can't figure out what rate it will be, so just return the - * rate back to the caller. scmi_clk_recalc_rate() will be called - * after the rate is set and we'll know what rate the clock is + * If we could not get a better rate scmi_clk_recalc_rate() will be + * called after the rate is set and we'll know what rate the clock is * running at then. */ - if (clk->info->rate_discrete) - return 0; - - fmin =3D clk->info->range.min_rate; - fmax =3D clk->info->range.max_rate; - if (req->rate <=3D fmin) { - req->rate =3D fmin; - - return 0; - } else if (req->rate >=3D fmax) { - req->rate =3D fmax; - - return 0; - } - - ftmp =3D req->rate - fmin; - ftmp +=3D clk->info->range.step_size - 1; /* to round up */ - do_div(ftmp, clk->info->range.step_size); - - req->rate =3D ftmp * clk->info->range.step_size + fmin; + ret =3D scmi_proto_clk_ops->determine_rate(clk->ph, clk->id, &req->rate); + if (ret) + return ret; =20 return 0; } --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3DC1A329E66; Fri, 27 Feb 2026 15:33:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206403; cv=none; b=YTuwt7bmMt+cGqpyqSP+3PhNFXygHqrsk8pFJ3mws/77vsJ1gAqzr5F1lnSz2QPT0DdHB5yuxdJvW1GRHz5ygyqiYfzM2B8gFdLSh9NMVeZw84yUBBgf/N2xuBOc8LHj5HNDSTVhnAUl8sJC2C9fIxysxAhkItLo7AFpzFIplXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206403; c=relaxed/simple; bh=1RDdoXQv8ByWzH0qtHjedbEuu4NTenKcqHV7lqJbm5o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fNMDZLZwxTlV6DSeweWk3rjJ5aedMhFoaxbvACS505WqViWRiP5Jjm1taJOR9K61bwPS/Ny2ivcEz+hobd/QHxhr6an3LO6G9eNlZLksfDFxSk4sH3mMfAvODDA98FjpF99R2Dj5akMODW03op8nOjj7ou5C4h9TCaMBhEfdjts= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 66A83339; Fri, 27 Feb 2026 07:33:15 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0E8D93F73B; Fri, 27 Feb 2026 07:33:13 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 03/11] firmware: arm_scmi: Simplify clock rates exposed interface Date: Fri, 27 Feb 2026 15:32:17 +0000 Message-ID: <20260227153225.2778358-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move needlessly exposed fields away from scmi_clock_info into the new internal struct scmi_clock_desc while keeping exposed only the two new min_rate and max_rate fields for each clock. No functional change. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 145 +++++++++++++++--------------- include/linux/scmi_protocol.h | 2 + 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index 54e8b59c3941..f5d1c608f85a 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -157,13 +157,27 @@ struct scmi_clock_rate_notify_payld { __le32 rate_high; }; =20 +struct scmi_clock_desc { + u32 id; + bool rate_discrete; + unsigned int num_rates; + u64 rates[SCMI_MAX_NUM_RATES]; +#define RATE_MIN 0 +#define RATE_MAX 1 +#define RATE_STEP 2 + struct scmi_clock_info info; +}; + +#define to_desc(p) (container_of((p), struct scmi_clock_desc, info)) + struct clock_info { int num_clocks; int max_async_req; bool notify_rate_changed_cmd; bool notify_rate_change_requested_cmd; atomic_t cur_async_req; - struct scmi_clock_info *clk; + struct scmi_clock_desc *clkds; +#define CLOCK_INFO(c, i) (&(((c)->clkds + (i))->info)) int (*clock_config_set)(const struct scmi_protocol_handle *ph, u32 clk_id, enum clk_state state, enum scmi_clock_oem_config oem_type, @@ -185,7 +199,7 @@ scmi_clock_domain_lookup(struct clock_info *ci, u32 clk= _id) if (clk_id >=3D ci->num_clocks) return ERR_PTR(-EINVAL); =20 - return ci->clk + clk_id; + return CLOCK_INFO(ci, clk_id); } =20 static int @@ -226,8 +240,7 @@ scmi_clock_protocol_attributes_get(const struct scmi_pr= otocol_handle *ph, =20 struct scmi_clk_ipriv { struct device *dev; - u32 clk_id; - struct scmi_clock_info *clk; + struct scmi_clock_desc *clkd; }; =20 static void iter_clk_possible_parents_prepare_message(void *message, unsig= ned int desc_index, @@ -236,7 +249,7 @@ static void iter_clk_possible_parents_prepare_message(v= oid *message, unsigned in struct scmi_msg_clock_possible_parents *msg =3D message; const struct scmi_clk_ipriv *p =3D priv; =20 - msg->id =3D cpu_to_le32(p->clk_id); + msg->id =3D cpu_to_le32(p->clkd->id); /* Set the number of OPPs to be skipped/already read */ msg->skip_parents =3D cpu_to_le32(desc_index); } @@ -246,7 +259,6 @@ static int iter_clk_possible_parents_update_state(struc= t scmi_iterator_state *st { const struct scmi_msg_resp_clock_possible_parents *r =3D response; struct scmi_clk_ipriv *p =3D priv; - struct device *dev =3D ((struct scmi_clk_ipriv *)p)->dev; u32 flags; =20 flags =3D le32_to_cpu(r->num_parent_flags); @@ -258,12 +270,13 @@ static int iter_clk_possible_parents_update_state(str= uct scmi_iterator_state *st * assume it's returned+remaining on first call. */ if (!st->max_resources) { - p->clk->num_parents =3D st->num_returned + st->num_remaining; - p->clk->parents =3D devm_kcalloc(dev, p->clk->num_parents, - sizeof(*p->clk->parents), - GFP_KERNEL); - if (!p->clk->parents) { - p->clk->num_parents =3D 0; + p->clkd->info.num_parents =3D st->num_returned + st->num_remaining; + p->clkd->info.parents =3D devm_kcalloc(p->dev, + p->clkd->info.num_parents, + sizeof(*p->clkd->info.parents), + GFP_KERNEL); + if (!p->clkd->info.parents) { + p->clkd->info.num_parents =3D 0; return -ENOMEM; } st->max_resources =3D st->num_returned + st->num_remaining; @@ -280,29 +293,27 @@ static int iter_clk_possible_parents_process_response= (const struct scmi_protocol const struct scmi_msg_resp_clock_possible_parents *r =3D response; struct scmi_clk_ipriv *p =3D priv; =20 - u32 *parent =3D &p->clk->parents[st->desc_index + st->loop_idx]; + u32 *parent =3D &p->clkd->info.parents[st->desc_index + st->loop_idx]; =20 *parent =3D le32_to_cpu(r->possible_parents[st->loop_idx]); =20 return 0; } =20 -static int scmi_clock_possible_parents(const struct scmi_protocol_handle *= ph, u32 clk_id, - struct scmi_clock_info *clk) +static int scmi_clock_possible_parents(const struct scmi_protocol_handle *= ph, + u32 clk_id, struct clock_info *cinfo) { struct scmi_iterator_ops ops =3D { .prepare_message =3D iter_clk_possible_parents_prepare_message, .update_state =3D iter_clk_possible_parents_update_state, .process_response =3D iter_clk_possible_parents_process_response, }; - + struct scmi_clock_desc *clkd =3D &cinfo->clkds[clk_id]; struct scmi_clk_ipriv ppriv =3D { - .clk_id =3D clk_id, - .clk =3D clk, + .clkd =3D clkd, .dev =3D ph->dev, }; void *iter; - int ret; =20 iter =3D ph->hops->iter_response_init(ph, &ops, 0, CLOCK_POSSIBLE_PARENTS_GET, @@ -311,9 +322,7 @@ static int scmi_clock_possible_parents(const struct scm= i_protocol_handle *ph, u3 if (IS_ERR(iter)) return PTR_ERR(iter); =20 - ret =3D ph->hops->iter_response_run(iter); - - return ret; + return ph->hops->iter_response_run(iter); } =20 static int @@ -352,7 +361,7 @@ static int scmi_clock_attributes_get(const struct scmi_= protocol_handle *ph, u32 attributes; struct scmi_xfer *t; struct scmi_msg_resp_clock_attributes *attr; - struct scmi_clock_info *clk =3D cinfo->clk + clk_id; + struct scmi_clock_info *clk =3D CLOCK_INFO(cinfo, clk_id); =20 ret =3D ph->xops->xfer_get_init(ph, CLOCK_ATTRIBUTES, sizeof(clk_id), sizeof(*attr), &t); @@ -394,7 +403,7 @@ static int scmi_clock_attributes_get(const struct scmi_= protocol_handle *ph, clk->rate_change_requested_notifications =3D true; if (PROTOCOL_REV_MAJOR(ph->version) >=3D 0x3) { if (SUPPORTS_PARENT_CLOCK(attributes)) - scmi_clock_possible_parents(ph, clk_id, clk); + scmi_clock_possible_parents(ph, clk_id, cinfo); if (SUPPORTS_GET_PERMISSIONS(attributes)) scmi_clock_get_permissions(ph, clk_id, clk); if (SUPPORTS_EXTENDED_CONFIG(attributes)) @@ -424,7 +433,7 @@ static void iter_clk_describe_prepare_message(void *mes= sage, struct scmi_msg_clock_describe_rates *msg =3D message; const struct scmi_clk_ipriv *p =3D priv; =20 - msg->id =3D cpu_to_le32(p->clk_id); + msg->id =3D cpu_to_le32(p->clkd->id); /* Set the number of rates to be skipped/already read */ msg->rate_index =3D cpu_to_le32(desc_index); } @@ -457,14 +466,14 @@ iter_clk_describe_update_state(struct scmi_iterator_s= tate *st, flags =3D le32_to_cpu(r->num_rates_flags); st->num_remaining =3D NUM_REMAINING(flags); st->num_returned =3D NUM_RETURNED(flags); - p->clk->rate_discrete =3D RATE_DISCRETE(flags); + p->clkd->rate_discrete =3D RATE_DISCRETE(flags); =20 /* Warn about out of spec replies ... */ - if (!p->clk->rate_discrete && + if (!p->clkd->rate_discrete && (st->num_returned !=3D 3 || st->num_remaining !=3D 0)) { dev_warn(p->dev, "Out-of-spec CLOCK_DESCRIBE_RATES reply for %s - returned:%d remaining= :%d rx_len:%zd\n", - p->clk->name, st->num_returned, st->num_remaining, + p->clkd->info.name, st->num_returned, st->num_remaining, st->rx_len); =20 SCMI_QUIRK(clock_rates_triplet_out_of_spec, @@ -479,38 +488,19 @@ iter_clk_describe_process_response(const struct scmi_= protocol_handle *ph, const void *response, struct scmi_iterator_state *st, void *priv) { - int ret =3D 0; struct scmi_clk_ipriv *p =3D priv; const struct scmi_msg_resp_clock_describe_rates *r =3D response; =20 - if (!p->clk->rate_discrete) { - switch (st->desc_index + st->loop_idx) { - case 0: - p->clk->range.min_rate =3D RATE_TO_U64(r->rate[0]); - break; - case 1: - p->clk->range.max_rate =3D RATE_TO_U64(r->rate[1]); - break; - case 2: - p->clk->range.step_size =3D RATE_TO_U64(r->rate[2]); - break; - default: - ret =3D -EINVAL; - break; - } - } else { - u64 *rate =3D &p->clk->list.rates[st->desc_index + st->loop_idx]; + p->clkd->rates[st->desc_index + st->loop_idx] =3D + RATE_TO_U64(r->rate[st->loop_idx]); + p->clkd->num_rates++; =20 - *rate =3D RATE_TO_U64(r->rate[st->loop_idx]); - p->clk->list.num_rates++; - } - - return ret; + return 0; } =20 static int scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 c= lk_id, - struct scmi_clock_info *clk) + struct clock_info *cinfo) { int ret; void *iter; @@ -519,9 +509,9 @@ scmi_clock_describe_rates_get(const struct scmi_protoco= l_handle *ph, u32 clk_id, .update_state =3D iter_clk_describe_update_state, .process_response =3D iter_clk_describe_process_response, }; + struct scmi_clock_desc *clkd =3D &cinfo->clkds[clk_id]; struct scmi_clk_ipriv cpriv =3D { - .clk_id =3D clk_id, - .clk =3D clk, + .clkd =3D clkd, .dev =3D ph->dev, }; =20 @@ -536,16 +526,23 @@ scmi_clock_describe_rates_get(const struct scmi_proto= col_handle *ph, u32 clk_id, if (ret) return ret; =20 - if (!clk->rate_discrete) { + /* empty set ? */ + if (!clkd->num_rates) + return 0; + + if (!clkd->rate_discrete) { + clkd->info.max_rate =3D clkd->rates[RATE_MAX]; dev_dbg(ph->dev, "Min %llu Max %llu Step %llu Hz\n", - clk->range.min_rate, clk->range.max_rate, - clk->range.step_size); - } else if (clk->list.num_rates) { - sort(clk->list.rates, clk->list.num_rates, - sizeof(clk->list.rates[0]), rate_cmp_func, NULL); + clkd->rates[RATE_MIN], clkd->rates[RATE_MAX], + clkd->rates[RATE_STEP]); + } else { + sort(clkd->rates, clkd->num_rates, + sizeof(clkd->rates[0]), rate_cmp_func, NULL); + clkd->info.max_rate =3D clkd->rates[clkd->num_rates - 1]; } + clkd->info.min_rate =3D clkd->rates[RATE_MIN]; =20 - return ret; + return 0; } =20 static int @@ -630,6 +627,7 @@ static int scmi_clock_determine_rate(const struct scmi_= protocol_handle *ph, { u64 fmin, fmax, ftmp; struct scmi_clock_info *clk; + struct scmi_clock_desc *clkd; struct clock_info *ci =3D ph->get_priv(ph); =20 if (!rate) @@ -639,15 +637,17 @@ static int scmi_clock_determine_rate(const struct scm= i_protocol_handle *ph, if (IS_ERR(clk)) return PTR_ERR(clk); =20 + clkd =3D to_desc(clk); + /* * If we can't figure out what rate it will be, so just return the * rate back to the caller. */ - if (clk->rate_discrete) + if (clkd->rate_discrete) return 0; =20 - fmin =3D clk->range.min_rate; - fmax =3D clk->range.max_rate; + fmin =3D clk->min_rate; + fmax =3D clk->max_rate; if (*rate <=3D fmin) { *rate =3D fmin; return 0; @@ -657,10 +657,10 @@ static int scmi_clock_determine_rate(const struct scm= i_protocol_handle *ph, } =20 ftmp =3D *rate - fmin; - ftmp +=3D clk->range.step_size - 1; /* to round up */ - do_div(ftmp, clk->range.step_size); + ftmp +=3D clkd->rates[RATE_STEP] - 1; /* to round up */ + do_div(ftmp, clkd->rates[RATE_STEP]); =20 - *rate =3D ftmp * clk->range.step_size + fmin; + *rate =3D ftmp * clkd->rates[RATE_STEP] + fmin; =20 return 0; } @@ -1122,17 +1122,16 @@ static int scmi_clock_protocol_init(const struct sc= mi_protocol_handle *ph) if (ret) return ret; =20 - cinfo->clk =3D devm_kcalloc(ph->dev, cinfo->num_clocks, - sizeof(*cinfo->clk), GFP_KERNEL); - if (!cinfo->clk) + cinfo->clkds =3D devm_kcalloc(ph->dev, cinfo->num_clocks, + sizeof(*cinfo->clkds), GFP_KERNEL); + if (!cinfo->clkds) return -ENOMEM; =20 for (clkid =3D 0; clkid < cinfo->num_clocks; clkid++) { - struct scmi_clock_info *clk =3D cinfo->clk + clkid; - + cinfo->clkds[clkid].id =3D clkid; ret =3D scmi_clock_attributes_get(ph, clkid, cinfo); if (!ret) - scmi_clock_describe_rates_get(ph, clkid, clk); + scmi_clock_describe_rates_get(ph, clkid, cinfo); } =20 if (PROTOCOL_REV_MAJOR(ph->version) >=3D 0x3) { diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 28579c145045..7283302b0c85 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -51,6 +51,8 @@ struct scmi_clock_info { bool rate_ctrl_forbidden; bool parent_ctrl_forbidden; bool extended_config; + u64 min_rate; + u64 max_rate; union { struct { int num_rates; --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 641DB43901F; Fri, 27 Feb 2026 15:33:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206411; cv=none; b=m1Pj9df5TZ7W17onFXKjUlBsppAaRZ06+c3GFJDx1gSHizirZTyXMipfUqPFWo4zDaKUmHXjWUR/BvQKDkPl0a1jSZyOQwPXTIVGx4eFWs68eKKHvN5VyDomBV1D4AbAIqT+MnG7XcbrhHXoBesXSmor03LLzTJVDsxgtd7St9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206411; c=relaxed/simple; bh=Tkd/258mwtchO7qfEmkltVc/PZJ7n6JXbNX9LHJ9lsA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f2t+uCjSOlMKgwb2w3qAPC7Ej8mtCODk4CcC+7e7OkXvWHRsRlIOnJd/mdsyu3fLBSI39WDv5Tix0vqD9X2TgQm4QBR4Oq4aathA4t9/lWs0L7SAe1DMwNHWCZQXCTT78Tj35nLXzWkRzDenP/FsWSNMDlK3mxrUjyyMaQ4lsns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 71A1B339; Fri, 27 Feb 2026 07:33:22 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8297B3F73B; Fri, 27 Feb 2026 07:33:22 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi , Michael Turquette , Stephen Boyd Subject: [PATCH 04/11] clk: scmi: Use new simplified per-clock rate properties Date: Fri, 27 Feb 2026 15:32:18 +0000 Message-ID: <20260227153225.2778358-5-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use the new min_rate and max_rate unified properties that provide the proper values without having to consider the clock type. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Reviewed-by: Peng Fan Tested-by: Geert Uytterhoeven --- drivers/clk/clk-scmi.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index c223e4ef1dd1..7c562559ad8b 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -202,7 +202,6 @@ static int scmi_clk_ops_init(struct device *dev, struct= scmi_clk *sclk, const struct clk_ops *scmi_ops) { int ret; - unsigned long min_rate, max_rate; =20 struct clk_init_data init =3D { .flags =3D CLK_GET_RATE_NOCACHE, @@ -217,20 +216,8 @@ static int scmi_clk_ops_init(struct device *dev, struc= t scmi_clk *sclk, if (ret) return ret; =20 - if (sclk->info->rate_discrete) { - int num_rates =3D sclk->info->list.num_rates; - - if (num_rates <=3D 0) - return -EINVAL; - - min_rate =3D sclk->info->list.rates[0]; - max_rate =3D sclk->info->list.rates[num_rates - 1]; - } else { - min_rate =3D sclk->info->range.min_rate; - max_rate =3D sclk->info->range.max_rate; - } - - clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate); + clk_hw_set_rate_range(&sclk->hw, sclk->info->min_rate, + sclk->info->max_rate); return ret; } =20 --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0D2353290A1; Fri, 27 Feb 2026 15:33:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206417; cv=none; b=QuCeRrLeXEwFMB+pKcLveNla+eE2h7svb4aL42KjlYErFzPH+ngMzFERSCnhrRllyLg01nsRm/tGDLL6a2Wz+1MPDBrR0tEjlfhMGCDboWjomJkptnHEST3WVRsujyMjxEXGvwrGqFBJE5ejY5u+XsWY19T3ROYTMmHFyhpwZrU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206417; c=relaxed/simple; bh=hosC0lf8QJPZBWpaH541Aizu9iGMXB9D/VZmiclacXw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kWw15CJ6HRqrIq2f7OgsuTLNXTxKW616u7ifOMIZByVOtrbOHjZNaGMkfKirHRXQ1uE6eOkzqcNmf36NCigAOkvq0zrnD0KdLvikThi+6qKX8519L8uvfR/wxP0nqkSjqe0v4YRbxkS5P7JLErkicwH1Pdgiu6JoapUsBWIcXhU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2642C339; Fri, 27 Feb 2026 07:33:29 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 687453F73B; Fri, 27 Feb 2026 07:33:29 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 05/11] firmware: arm_scmi: Drop unused clock rate interfaces Date: Fri, 27 Feb 2026 15:32:19 +0000 Message-ID: <20260227153225.2778358-6-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Only the unified interface exposing min_rate/max_rate is now used. Signed-off-by: Cristian Marussi Reviewed-by: Peng Fan Tested-by: Geert Uytterhoeven --- include/linux/scmi_protocol.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 7283302b0c85..d97b4e734744 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -53,17 +53,6 @@ struct scmi_clock_info { bool extended_config; u64 min_rate; u64 max_rate; - union { - struct { - int num_rates; - u64 rates[SCMI_MAX_NUM_RATES]; - } list; - struct { - u64 min_rate; - u64 max_rate; - u64 step_size; - } range; - }; int num_parents; u32 *parents; }; --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D633B43D4E4; Fri, 27 Feb 2026 15:33:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206424; cv=none; b=NeUrqx0jVjXSvVgutIaHQ8M7/MaD4WL27ATHLmjMHfcklUDWVtXbtgG+RAhBr4feZdH8lycnLrGbzBUVK9t0X83qkbZNo2KyUhvhhI+1l0696+xwHAS5ksOsKiDsw8FqW4fxdqomBuzqWLiDBXkjjftx1IVJntAKtwO0rGcDPDk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206424; c=relaxed/simple; bh=FPNIPV8Y68QYStm4ZPE7dPkSR3ncymanrnqOV1af5lw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ENST93XAU//6MJGYlNyQAhWrezeZlWZe5wFz3V+ua6Zaw7QUVGatCRnztLTXBGQfYl0JiUvLOZy7ai3g65L5OtYNagzqtB/nRLC93ZKcmc9QUw6rQEzEfo393Eyek5dF5ReNYMST1/gyroVbiQiOYeFka/omJ6X52oO6qONvV8Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0C59A339; Fri, 27 Feb 2026 07:33:36 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 00B203F73B; Fri, 27 Feb 2026 07:33:35 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 06/11] firmware: arm_scmi: Make clock rates allocation dynamic Date: Fri, 27 Feb 2026 15:32:20 +0000 Message-ID: <20260227153225.2778358-7-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Leveraging SCMI Clock protocol dynamic discovery capabilities, move away from the static per-clock rates allocation model in favour of a dynamic runtime allocation based on effectively discovered resources. No functional change. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 19 ++++++++++++++++--- include/linux/scmi_protocol.h | 1 - 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index f5d1c608f85a..d0fb5affb5cf 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -161,7 +161,7 @@ struct scmi_clock_desc { u32 id; bool rate_discrete; unsigned int num_rates; - u64 rates[SCMI_MAX_NUM_RATES]; + u64 *rates; #define RATE_MIN 0 #define RATE_MAX 1 #define RATE_STEP 2 @@ -480,6 +480,18 @@ iter_clk_describe_update_state(struct scmi_iterator_st= ate *st, QUIRK_OUT_OF_SPEC_TRIPLET); } =20 + if (!st->max_resources) { + int num_rates =3D st->num_returned + st->num_remaining; + + p->clkd->rates =3D devm_kcalloc(p->dev, num_rates, + sizeof(*p->clkd->rates), GFP_KERNEL); + if (!p->clkd->rates) + return -ENOMEM; + + /* max_resources is used by the iterators to control bounds */ + st->max_resources =3D st->num_returned + st->num_remaining; + } + return 0; } =20 @@ -493,6 +505,8 @@ iter_clk_describe_process_response(const struct scmi_pr= otocol_handle *ph, =20 p->clkd->rates[st->desc_index + st->loop_idx] =3D RATE_TO_U64(r->rate[st->loop_idx]); + + /* Count only effectively discovered rates */ p->clkd->num_rates++; =20 return 0; @@ -515,8 +529,7 @@ scmi_clock_describe_rates_get(const struct scmi_protoco= l_handle *ph, u32 clk_id, .dev =3D ph->dev, }; =20 - iter =3D ph->hops->iter_response_init(ph, &ops, SCMI_MAX_NUM_RATES, - CLOCK_DESCRIBE_RATES, + iter =3D ph->hops->iter_response_init(ph, &ops, 0, CLOCK_DESCRIBE_RATES, sizeof(struct scmi_msg_clock_describe_rates), &cpriv); if (IS_ERR(iter)) diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index d97b4e734744..5552ac04c820 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -15,7 +15,6 @@ =20 #define SCMI_MAX_STR_SIZE 64 #define SCMI_SHORT_NAME_MAX_SIZE 16 -#define SCMI_MAX_NUM_RATES 16 =20 /** * struct scmi_revision_info - version information structure --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7A21642DFF4; Fri, 27 Feb 2026 15:33:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206430; cv=none; b=VQ19uNGwF9EB7VOa/hoyM5rK9ozIpPiz9jvdxj5dtt59cNzVfF8dDiP6Z3RNKaniTfQUfVvRWcZC7SZ/5ZxM3dpKR21icsJODjhqp4AF+upsRil8T8Eql4y6OYJTSfFgxtpspGW3jDPtkCRn9e2qH2THKbQp8spnPa1Dmcod/Pc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206430; c=relaxed/simple; bh=xt0wu3Wd2P1k772XH3PuN3JSJ43nTtfOh6/MjiV21Ts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tFcSS0o/DnDY6BgezyRF6OUFLoyMt0cb2l9Iw2mzNhi0Cb/oobZF4ZJVt1whOX2zPJLLu3GG873i+27NkcZgiwOhJX6Hg3wk1PILIgtHMk4yTwCc5p5rSRLwRh5e3Lrbs4LSrCjih6nX/nDowHyR7guEhNi425iNb0+GUuQ6Xvw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8EE02339; Fri, 27 Feb 2026 07:33:42 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CE5453F73B; Fri, 27 Feb 2026 07:33:42 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 07/11] firmware: arm_scmi: Harden clock parents discovery Date: Fri, 27 Feb 2026 15:32:21 +0000 Message-ID: <20260227153225.2778358-8-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Fix clock parents enumeration to account only for effectively discovered parents during enumeration, avoiding to trust the total number of parents declared upfront by the platform. Signed-off-by: Cristian Marussi Reviewed-by: Peng Fan Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index d0fb5affb5cf..15faa79abed4 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -270,15 +270,15 @@ static int iter_clk_possible_parents_update_state(str= uct scmi_iterator_state *st * assume it's returned+remaining on first call. */ if (!st->max_resources) { - p->clkd->info.num_parents =3D st->num_returned + st->num_remaining; - p->clkd->info.parents =3D devm_kcalloc(p->dev, - p->clkd->info.num_parents, + int num_parents =3D st->num_returned + st->num_remaining; + + p->clkd->info.parents =3D devm_kcalloc(p->dev, num_parents, sizeof(*p->clkd->info.parents), GFP_KERNEL); - if (!p->clkd->info.parents) { - p->clkd->info.num_parents =3D 0; + if (!p->clkd->info.parents) return -ENOMEM; - } + + /* max_resources is used by the iterators to control bounds */ st->max_resources =3D st->num_returned + st->num_remaining; } =20 @@ -293,9 +293,11 @@ static int iter_clk_possible_parents_process_response(= const struct scmi_protocol const struct scmi_msg_resp_clock_possible_parents *r =3D response; struct scmi_clk_ipriv *p =3D priv; =20 - u32 *parent =3D &p->clkd->info.parents[st->desc_index + st->loop_idx]; + p->clkd->info.parents[st->desc_index + st->loop_idx] =3D + le32_to_cpu(r->possible_parents[st->loop_idx]); =20 - *parent =3D le32_to_cpu(r->possible_parents[st->loop_idx]); + /* Count only effectively discovered parents */ + p->clkd->info.num_parents++; =20 return 0; } --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 824CA3290A1; Fri, 27 Feb 2026 15:33:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206438; cv=none; b=BwXy/0UEzf0ew+Y2hGgAUMy9cfhP9wqGMyeROoVlYfmEyfVVJaEkMhTG50Bn40gY/jzAEHYOOBCYqvB2fBcjBjkipgpkeN5uNrzmRJBdph8HqNmC9oyxyDV9qRvwo8R3OZFpYt69Diya58NN++1dS6nxLmu3KefcD4NIwKhmGbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206438; c=relaxed/simple; bh=t6Hj+PFhx1Jd+Y7VMJSrSjsEfVZ19zlNTAlw4Q7T+LQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u2eIS/dowTVV/9TOcQiMgs0nCzSIAk2kd/+wwPr/vtPp6Ye5E8KsDTmUQAZclyy+oxSuNxwNVhRr24xTHzs+rhX9iNn88sauAAU6OtXMb7fU3kLbwBpfEux0PWtZD/p71JUHV0YwxQEiw+v1B668wCNABeKYTGNScknPxSFtD1c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AF99F339; Fri, 27 Feb 2026 07:33:49 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8F8923F73B; Fri, 27 Feb 2026 07:33:49 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 08/11] firmware: arm_scmi: Refactor iterators internal allocation Date: Fri, 27 Feb 2026 15:32:22 +0000 Message-ID: <20260227153225.2778358-9-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use cleanup handlers to manage iterator data structures. No functional change. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/driver.c | 35 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index baefa7d43c00..d9d6edbc1275 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -17,6 +17,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 #include +#include #include #include #include @@ -1789,39 +1790,41 @@ static void *scmi_iterator_init(const struct scmi_p= rotocol_handle *ph, size_t tx_size, void *priv) { int ret; - struct scmi_iterator *i; =20 - i =3D devm_kzalloc(ph->dev, sizeof(*i), GFP_KERNEL); + struct scmi_iterator *i __free(kfree) =3D kzalloc(sizeof(*i), GFP_KERNEL); if (!i) return ERR_PTR(-ENOMEM); =20 + if (!ops || !ph) + return ERR_PTR(-EINVAL); + i->ph =3D ph; i->ops =3D ops; i->priv =3D priv; =20 ret =3D ph->xops->xfer_get_init(ph, msg_id, tx_size, 0, &i->t); - if (ret) { - devm_kfree(ph->dev, i); + if (ret) return ERR_PTR(ret); - } =20 i->state.max_resources =3D max_resources; i->msg =3D i->t->tx.buf; i->resp =3D i->t->rx.buf; =20 - return i; + return no_free_ptr(i); } =20 static int scmi_iterator_run(void *iter) { - int ret =3D -EINVAL; + int ret; struct scmi_iterator_ops *iops; const struct scmi_protocol_handle *ph; struct scmi_iterator_state *st; - struct scmi_iterator *i =3D iter; =20 - if (!i || !i->ops || !i->ph) - return ret; + if (!iter) + return -EINVAL; + + /* Take ownership of the iterator */ + struct scmi_iterator *i __free(kfree) =3D iter; =20 iops =3D i->ops; ph =3D i->ph; @@ -1846,12 +1849,12 @@ static int scmi_iterator_run(void *iter) break; } =20 - for (st->loop_idx =3D 0; st->loop_idx < st->num_returned; - st->loop_idx++) { + for (st->loop_idx =3D 0; !ret && st->loop_idx < st->num_returned; + st->loop_idx++) ret =3D iops->process_response(ph, i->resp, st, i->priv); - if (ret) - goto out; - } + + if (ret) + break; =20 st->desc_index +=3D st->num_returned; ph->xops->reset_rx_to_maxsz(ph, i->t); @@ -1861,10 +1864,8 @@ static int scmi_iterator_run(void *iter) */ } while (st->num_returned && st->num_remaining); =20 -out: /* Finalize and destroy iterator */ ph->xops->xfer_put(ph, i->t); - devm_kfree(ph->dev, i); =20 return ret; } --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9F2F243CEF9; Fri, 27 Feb 2026 15:34:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206445; cv=none; b=UKEG5HswmtcE02uphYTPHhGDF2QZQ1X30AiYA/DR2EawYKKFShpR29WahdqRlyfbNQP3f5tcKEXKzYLYyNE6uVcIPTsCkKX4Nel8ZomwLdxADCOE8/15SBmRyYBkpbKHzcZjmp1Oxciq0wiDdpuDMYw2xdMxLx0A1sLhbg2iZEA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206445; c=relaxed/simple; bh=o1wyGFFzv1WlO61N6heUNvXWChi57n1OuASyQQfpiAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gcA6TNsnxJo4i2vzE0wae2on9CR0CdukpLQBTBXT6AaLZ2w0Vdg7YYQMZDHEDHvsZ+ZlUwkGaZbRjhfoOTAR17jbwGo7E9SNduBDE/YODJEEHTY4EpanmrPxCp9ygO/0vFrFIMe+eB070ZZwPcwA+1VoTzp/CIETBtsre+4qL1c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BCD18339; Fri, 27 Feb 2026 07:33:56 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BB7EF3F73B; Fri, 27 Feb 2026 07:33:56 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 09/11] firmware: arm_scmi: Add bound iterators support Date: Fri, 27 Feb 2026 15:32:23 +0000 Message-ID: <20260227153225.2778358-10-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" SCMI core stack provides some common helpers to handle in a unified way multipart message replies: such iterator-helpers, when run, currently process by default the whole set of discovered resources. Introduce an alternative way to run the initialized iterator on a limited range of resources. Note that the subset of resources that can be chosen is anyway limited by the SCMI protocol specification, since you are only allowed to choose the startindex on a multi-part enumeration NOT the end index, so that the effective number of returned items by a bound iterators depends really on platform side decisions. Suggested-by: Etienne Carriere Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 3 +- drivers/firmware/arm_scmi/driver.c | 58 +++++++++++++++++++-------- drivers/firmware/arm_scmi/protocols.h | 13 +++++- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index 15faa79abed4..d7df5c45836e 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -505,8 +505,7 @@ iter_clk_describe_process_response(const struct scmi_pr= otocol_handle *ph, struct scmi_clk_ipriv *p =3D priv; const struct scmi_msg_resp_clock_describe_rates *r =3D response; =20 - p->clkd->rates[st->desc_index + st->loop_idx] =3D - RATE_TO_U64(r->rate[st->loop_idx]); + p->clkd->rates[p->clkd->num_rates] =3D RATE_TO_U64(r->rate[st->loop_idx]); =20 /* Count only effectively discovered rates */ p->clkd->num_rates++; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi= /driver.c index d9d6edbc1275..299265d05f62 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1813,48 +1813,50 @@ static void *scmi_iterator_init(const struct scmi_p= rotocol_handle *ph, return no_free_ptr(i); } =20 -static int scmi_iterator_run(void *iter) +static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned i= nt *end) { int ret; struct scmi_iterator_ops *iops; const struct scmi_protocol_handle *ph; struct scmi_iterator_state *st; + struct scmi_iterator *i; =20 if (!iter) return -EINVAL; =20 - /* Take ownership of the iterator */ - struct scmi_iterator *i __free(kfree) =3D iter; - + i =3D iter; iops =3D i->ops; ph =3D i->ph; st =3D &i->state; =20 + /* Reinitialize state for next run */ + st->num_returned =3D 0; + st->num_remaining =3D 0; + st->desc_index =3D start ? *start : 0; + do { iops->prepare_message(i->msg, st->desc_index, i->priv); ret =3D ph->xops->do_xfer(ph, i->t); if (ret) - break; + return ret; =20 st->rx_len =3D i->t->rx.len; ret =3D iops->update_state(st, i->resp, i->priv); if (ret) - break; + return ret; =20 if (st->num_returned > st->max_resources - st->desc_index) { dev_err(ph->dev, "No. of resources can't exceed %d\n", st->max_resources); - ret =3D -EINVAL; - break; + return -EINVAL; } =20 - for (st->loop_idx =3D 0; !ret && st->loop_idx < st->num_returned; - st->loop_idx++) + for (st->loop_idx =3D 0; st->loop_idx < st->num_returned; st->loop_idx++= ) { ret =3D iops->process_response(ph, i->resp, st, i->priv); - - if (ret) - break; + if (ret) + return ret; + } =20 st->desc_index +=3D st->num_returned; ph->xops->reset_rx_to_maxsz(ph, i->t); @@ -1862,14 +1864,36 @@ static int scmi_iterator_run(void *iter) * check for both returned and remaining to avoid infinite * loop due to buggy firmware */ - } while (st->num_returned && st->num_remaining); + } while (st->num_returned && st->num_remaining && + (!end || (st->desc_index <=3D min(*end, st->max_resources - 1)))); =20 - /* Finalize and destroy iterator */ - ph->xops->xfer_put(ph, i->t); + return 0; +} + +static void scmi_iterator_cleanup(void *iter) +{ + struct scmi_iterator *i =3D iter; + + i->ph->xops->xfer_put(i->ph, i->t); + kfree(i); +} + +static int scmi_iterator_run(void *iter) +{ + int ret; + + ret =3D __scmi_iterator_run(iter, NULL, NULL); + scmi_iterator_cleanup(iter); =20 return ret; } =20 +static int scmi_iterator_run_bound(void *iter, unsigned int *start, + unsigned int *end) +{ + return __scmi_iterator_run(iter, start, end); +} + struct scmi_msg_get_fc_info { __le32 domain; __le32 message_id; @@ -2048,6 +2072,8 @@ static const struct scmi_proto_helpers_ops helpers_op= s =3D { .get_max_msg_size =3D scmi_common_get_max_msg_size, .iter_response_init =3D scmi_iterator_init, .iter_response_run =3D scmi_iterator_run, + .iter_response_run_bound =3D scmi_iterator_run_bound, + .iter_response_cleanup =3D scmi_iterator_cleanup, .protocol_msg_check =3D scmi_protocol_msg_check, .fastchannel_init =3D scmi_common_fastchannel_init, .fastchannel_db_ring =3D scmi_common_fastchannel_db_ring, diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_s= cmi/protocols.h index 4c75970326e6..487f84239385 100644 --- a/drivers/firmware/arm_scmi/protocols.h +++ b/drivers/firmware/arm_scmi/protocols.h @@ -259,7 +259,15 @@ struct scmi_fc_info { * multi-part responses using the custom operations * provided in @ops. * @iter_response_run: A common helper to trigger the run of a previously - * initialized iterator. + * initialized iterator. Note that unbound iterators are + * automatically cleaned up. + * @iter_response_run_bound: A common helper to trigger the run of a previ= ously + * initialized iterator, but only within the + * specified, optional, @start and @end resource + * indexes. Note that these bound-iterators need + * explicit cleanup via @iter_response_bound_cleanup. + * @iter_response_bound_cleanup: A common helper to finally release the it= erator + * for bound iterators. * @protocol_msg_check: A common helper to check is a specific protocol me= ssage * is supported. * @fastchannel_init: A common helper used to initialize FC descriptors by @@ -276,6 +284,9 @@ struct scmi_proto_helpers_ops { unsigned int max_resources, u8 msg_id, size_t tx_size, void *priv); int (*iter_response_run)(void *iter); + int (*iter_response_run_bound)(void *iter, + unsigned int *start, unsigned int *end); + void (*iter_response_cleanup)(void *iter); int (*protocol_msg_check)(const struct scmi_protocol_handle *ph, u32 message_id, u32 *attributes); void (*fastchannel_init)(const struct scmi_protocol_handle *ph, --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A0D7543E497; Fri, 27 Feb 2026 15:34:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206453; cv=none; b=qOTiJEq3ukMzmD7kcmVNy0RuZ1ZIlngEtiUw9STGLnDoqNrqqKig93W97mhAbyN4Myxh/runvQDULi6iFpLOWC+HMDvoElGyd/ZLyBJkMx6uZn0ZfHp0pksKR92f2N0OreYq/Fb1sOm/uX9DzYr7cXfSbyFCou2V+7FiPlPimZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206453; c=relaxed/simple; bh=jCtpdtL9Oa4C9wz/4HfV2UAWvexwgg0RKr0p33wNXec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GdBuPNdTgpQqWt3a4aJBySNjulC5ilouxquBAPXtDRzXLqRCkYkKSWEuIeJwZ2FjgUz3zJZNP2wErXqxbtDSzE7zWjpZhdeOcfBBEXonzSKUiI1ysPn7z5eMUGyMbrtkZ//DWk5+C+QhcWx8umCfLauYgMazxW/MIsALJU6O+K0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B2C92339; Fri, 27 Feb 2026 07:34:04 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BCBB63F73B; Fri, 27 Feb 2026 07:34:03 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 10/11] firmware: arm_scmi: Use bound iterators to minimize discovered rates Date: Fri, 27 Feb 2026 15:32:24 +0000 Message-ID: <20260227153225.2778358-11-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Clock rates are guaranteed to be returned in ascending order for SCMI clock protocol versions greater than 1.0: in such a case, use bounded iterators to minimize the number of message exchanges needed to discover min and max rate. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 92 +++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index d7df5c45836e..a0de10652abe 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -160,6 +160,7 @@ struct scmi_clock_rate_notify_payld { struct scmi_clock_desc { u32 id; bool rate_discrete; + unsigned int tot_rates; unsigned int num_rates; u64 *rates; #define RATE_MIN 0 @@ -483,15 +484,16 @@ iter_clk_describe_update_state(struct scmi_iterator_s= tate *st, } =20 if (!st->max_resources) { - int num_rates =3D st->num_returned + st->num_remaining; + unsigned int tot_rates =3D st->num_returned + st->num_remaining; =20 - p->clkd->rates =3D devm_kcalloc(p->dev, num_rates, + p->clkd->rates =3D devm_kcalloc(p->dev, tot_rates, sizeof(*p->clkd->rates), GFP_KERNEL); if (!p->clkd->rates) return -ENOMEM; =20 /* max_resources is used by the iterators to control bounds */ - st->max_resources =3D st->num_returned + st->num_remaining; + p->clkd->tot_rates =3D tot_rates; + st->max_resources =3D tot_rates; } =20 return 0; @@ -514,8 +516,8 @@ iter_clk_describe_process_response(const struct scmi_pr= otocol_handle *ph, } =20 static int -scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 c= lk_id, - struct clock_info *cinfo) +scmi_clock_describe_rates_get_full(const struct scmi_protocol_handle *ph, + struct scmi_clock_desc *clkd) { int ret; void *iter; @@ -524,7 +526,6 @@ scmi_clock_describe_rates_get(const struct scmi_protoco= l_handle *ph, u32 clk_id, .update_state =3D iter_clk_describe_update_state, .process_response =3D iter_clk_describe_process_response, }; - struct scmi_clock_desc *clkd =3D &cinfo->clkds[clk_id]; struct scmi_clk_ipriv cpriv =3D { .clkd =3D clkd, .dev =3D ph->dev, @@ -544,19 +545,90 @@ scmi_clock_describe_rates_get(const struct scmi_proto= col_handle *ph, u32 clk_id, if (!clkd->num_rates) return 0; =20 + if (clkd->rate_discrete) + sort(clkd->rates, clkd->num_rates, + sizeof(clkd->rates[0]), rate_cmp_func, NULL); + + return 0; +} + +static int +scmi_clock_describe_rates_get_lazy(const struct scmi_protocol_handle *ph, + struct scmi_clock_desc *clkd) +{ + struct scmi_iterator_ops ops =3D { + .prepare_message =3D iter_clk_describe_prepare_message, + .update_state =3D iter_clk_describe_update_state, + .process_response =3D iter_clk_describe_process_response, + }; + struct scmi_clk_ipriv cpriv =3D { + .clkd =3D clkd, + .dev =3D ph->dev, + }; + unsigned int first, last; + void *iter; + int ret; + + iter =3D ph->hops->iter_response_init(ph, &ops, 0, CLOCK_DESCRIBE_RATES, + sizeof(struct scmi_msg_clock_describe_rates), + &cpriv); + if (IS_ERR(iter)) + return PTR_ERR(iter); + + /* Try to grab a triplet, so that in case is NON-discrete we are done */ + first =3D 0; + last =3D 2; + ret =3D ph->hops->iter_response_run_bound(iter, &first, &last); + if (ret) + goto out; + + /* If discrete grab the last value, which should be the max */ + if (clkd->rate_discrete && clkd->tot_rates > 3) { + first =3D clkd->tot_rates - 1; + last =3D clkd->tot_rates - 1; + ret =3D ph->hops->iter_response_run_bound(iter, &first, &last); + } + +out: + ph->hops->iter_response_cleanup(iter); + + return ret; +} + +static int +scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, + u32 clk_id, struct clock_info *cinfo) +{ + struct scmi_clock_desc *clkd =3D &cinfo->clkds[clk_id]; + int ret; + + /* + * Since only after SCMI Clock v1.0 the returned rates are guaranteed to + * be discovered in ascending order, lazy enumeration cannot be use for + * SCMI Clock v1.0 protocol. + */ + if (PROTOCOL_REV_MAJOR(ph->version) > 0x1) + ret =3D scmi_clock_describe_rates_get_lazy(ph, clkd); + else + ret =3D scmi_clock_describe_rates_get_full(ph, clkd); + + if (ret) + return ret; + + clkd->info.min_rate =3D clkd->rates[RATE_MIN]; if (!clkd->rate_discrete) { clkd->info.max_rate =3D clkd->rates[RATE_MAX]; dev_dbg(ph->dev, "Min %llu Max %llu Step %llu Hz\n", clkd->rates[RATE_MIN], clkd->rates[RATE_MAX], clkd->rates[RATE_STEP]); } else { - sort(clkd->rates, clkd->num_rates, - sizeof(clkd->rates[0]), rate_cmp_func, NULL); clkd->info.max_rate =3D clkd->rates[clkd->num_rates - 1]; + dev_dbg(ph->dev, "Clock:%s DISCRETE:%d -> Min %llu Max %llu\n", + clkd->info.name, clkd->rate_discrete, + clkd->info.min_rate, clkd->info.max_rate); } - clkd->info.min_rate =3D clkd->rates[RATE_MIN]; =20 - return 0; + return ret; } =20 static int --=20 2.53.0 From nobody Thu Jun 11 00:36:12 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D595D43DA2E; Fri, 27 Feb 2026 15:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206460; cv=none; b=t9ziKoZMDrR2t2J987iRJypdKlUig7hFspNcWmEtwd6qfWXGeErvY/VIYZZAB4YUt2d/88rDjJfiydtVjrAfwPyXWt5z+Y/0V0tm9Sx9pllr/JfpWJKcC8G+40xAFhVPDSeuKh8b4DRUQyzq/BOhKGAgfmeyr5W3NT5pK1gLAWY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772206460; c=relaxed/simple; bh=cDmyGhVRBAXTAOsnBaTbIhCabwry7zDHpYdYX7wGMMw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JBMBpTFWQTW3sbP6kLVE+nt/qTMam+14EC9AoCIyQ8FVUPZGrAVyxC1UIF6pxserwb26LT7/qhYJclnGz+TR5hH1e6Xd593JlUTo0EzBmSy7vUQnVfmO7OTJmslNzpDhBKWHv4/o45USmya0A7De9IXwjsAd1RsZzxV/QAxo+/k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2C0DC339; Fri, 27 Feb 2026 07:34:12 -0800 (PST) Received: from pluto (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BAC343F73B; Fri, 27 Feb 2026 07:34:11 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-clk@vger.kernel.org, linux-renesas-soc@vger.kernel.org Cc: sudeep.holla@arm.com, philip.radford@arm.com, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@foss.st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com, marek.vasut+renesas@gmail.com, Cristian Marussi Subject: [PATCH 11/11] firmware: arm_scmi: Introduce all_rates_get clock operation Date: Fri, 27 Feb 2026 15:32:25 +0000 Message-ID: <20260227153225.2778358-12-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260227153225.2778358-1-cristian.marussi@arm.com> References: <20260227153225.2778358-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a clock operation to get the whole set of rates available to a specific clock: when needed this request could transparently trigger a full rate discovery enumeration if this specific clock-rates were previously only lazily enumerated. Signed-off-by: Cristian Marussi Tested-by: Geert Uytterhoeven --- drivers/firmware/arm_scmi/clock.c | 85 +++++++++++++++++++++---------- include/linux/scmi_protocol.h | 9 ++++ 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/= clock.c index a0de10652abe..c2fd9a1c3316 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -159,10 +159,8 @@ struct scmi_clock_rate_notify_payld { =20 struct scmi_clock_desc { u32 id; - bool rate_discrete; unsigned int tot_rates; - unsigned int num_rates; - u64 *rates; + struct scmi_clock_rates r; #define RATE_MIN 0 #define RATE_MAX 1 #define RATE_STEP 2 @@ -469,10 +467,10 @@ iter_clk_describe_update_state(struct scmi_iterator_s= tate *st, flags =3D le32_to_cpu(r->num_rates_flags); st->num_remaining =3D NUM_REMAINING(flags); st->num_returned =3D NUM_RETURNED(flags); - p->clkd->rate_discrete =3D RATE_DISCRETE(flags); + p->clkd->r.rate_discrete =3D RATE_DISCRETE(flags); =20 /* Warn about out of spec replies ... */ - if (!p->clkd->rate_discrete && + if (!p->clkd->r.rate_discrete && (st->num_returned !=3D 3 || st->num_remaining !=3D 0)) { dev_warn(p->dev, "Out-of-spec CLOCK_DESCRIBE_RATES reply for %s - returned:%d remaining= :%d rx_len:%zd\n", @@ -486,9 +484,9 @@ iter_clk_describe_update_state(struct scmi_iterator_sta= te *st, if (!st->max_resources) { unsigned int tot_rates =3D st->num_returned + st->num_remaining; =20 - p->clkd->rates =3D devm_kcalloc(p->dev, tot_rates, - sizeof(*p->clkd->rates), GFP_KERNEL); - if (!p->clkd->rates) + p->clkd->r.rates =3D devm_kcalloc(p->dev, tot_rates, + sizeof(*p->clkd->r.rates), GFP_KERNEL); + if (!p->clkd->r.rates) return -ENOMEM; =20 /* max_resources is used by the iterators to control bounds */ @@ -507,10 +505,10 @@ iter_clk_describe_process_response(const struct scmi_= protocol_handle *ph, struct scmi_clk_ipriv *p =3D priv; const struct scmi_msg_resp_clock_describe_rates *r =3D response; =20 - p->clkd->rates[p->clkd->num_rates] =3D RATE_TO_U64(r->rate[st->loop_idx]); + p->clkd->r.rates[p->clkd->r.num_rates] =3D RATE_TO_U64(r->rate[st->loop_i= dx]); =20 /* Count only effectively discovered rates */ - p->clkd->num_rates++; + p->clkd->r.num_rates++; =20 return 0; } @@ -531,7 +529,13 @@ scmi_clock_describe_rates_get_full(const struct scmi_p= rotocol_handle *ph, .dev =3D ph->dev, }; =20 - iter =3D ph->hops->iter_response_init(ph, &ops, 0, CLOCK_DESCRIBE_RATES, + /* + * Using tot_rates as max_resources parameter here so as to trigger + * the dynamic allocation only when strictly needed: when trying a + * full enumeration after a lazy one tot_rates will be non-zero. + */ + iter =3D ph->hops->iter_response_init(ph, &ops, clkd->tot_rates, + CLOCK_DESCRIBE_RATES, sizeof(struct scmi_msg_clock_describe_rates), &cpriv); if (IS_ERR(iter)) @@ -542,12 +546,12 @@ scmi_clock_describe_rates_get_full(const struct scmi_= protocol_handle *ph, return ret; =20 /* empty set ? */ - if (!clkd->num_rates) + if (!clkd->r.num_rates) return 0; =20 - if (clkd->rate_discrete) - sort(clkd->rates, clkd->num_rates, - sizeof(clkd->rates[0]), rate_cmp_func, NULL); + if (clkd->r.rate_discrete && PROTOCOL_REV_MAJOR(ph->version) =3D=3D 0x1) + sort(clkd->r.rates, clkd->r.num_rates, + sizeof(clkd->r.rates[0]), rate_cmp_func, NULL); =20 return 0; } @@ -583,7 +587,7 @@ scmi_clock_describe_rates_get_lazy(const struct scmi_pr= otocol_handle *ph, goto out; =20 /* If discrete grab the last value, which should be the max */ - if (clkd->rate_discrete && clkd->tot_rates > 3) { + if (clkd->r.rate_discrete && clkd->tot_rates > 3) { first =3D clkd->tot_rates - 1; last =3D clkd->tot_rates - 1; ret =3D ph->hops->iter_response_run_bound(iter, &first, &last); @@ -615,16 +619,16 @@ scmi_clock_describe_rates_get(const struct scmi_proto= col_handle *ph, if (ret) return ret; =20 - clkd->info.min_rate =3D clkd->rates[RATE_MIN]; - if (!clkd->rate_discrete) { - clkd->info.max_rate =3D clkd->rates[RATE_MAX]; + clkd->info.min_rate =3D clkd->r.rates[RATE_MIN]; + if (!clkd->r.rate_discrete) { + clkd->info.max_rate =3D clkd->r.rates[RATE_MAX]; dev_dbg(ph->dev, "Min %llu Max %llu Step %llu Hz\n", - clkd->rates[RATE_MIN], clkd->rates[RATE_MAX], - clkd->rates[RATE_STEP]); + clkd->r.rates[RATE_MIN], clkd->r.rates[RATE_MAX], + clkd->r.rates[RATE_STEP]); } else { - clkd->info.max_rate =3D clkd->rates[clkd->num_rates - 1]; + clkd->info.max_rate =3D clkd->r.rates[clkd->r.num_rates - 1]; dev_dbg(ph->dev, "Clock:%s DISCRETE:%d -> Min %llu Max %llu\n", - clkd->info.name, clkd->rate_discrete, + clkd->info.name, clkd->r.rate_discrete, clkd->info.min_rate, clkd->info.max_rate); } =20 @@ -729,7 +733,7 @@ static int scmi_clock_determine_rate(const struct scmi_= protocol_handle *ph, * If we can't figure out what rate it will be, so just return the * rate back to the caller. */ - if (clkd->rate_discrete) + if (clkd->r.rate_discrete) return 0; =20 fmin =3D clk->min_rate; @@ -743,14 +747,40 @@ static int scmi_clock_determine_rate(const struct scm= i_protocol_handle *ph, } =20 ftmp =3D *rate - fmin; - ftmp +=3D clkd->rates[RATE_STEP] - 1; /* to round up */ - do_div(ftmp, clkd->rates[RATE_STEP]); + ftmp +=3D clkd->r.rates[RATE_STEP] - 1; /* to round up */ + do_div(ftmp, clkd->r.rates[RATE_STEP]); =20 - *rate =3D ftmp * clkd->rates[RATE_STEP] + fmin; + *rate =3D ftmp * clkd->r.rates[RATE_STEP] + fmin; =20 return 0; } =20 +static const struct scmi_clock_rates * +scmi_clock_all_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id) +{ + struct clock_info *ci =3D ph->get_priv(ph); + struct scmi_clock_desc *clkd; + struct scmi_clock_info *clk; + + clk =3D scmi_clock_domain_lookup(ci, clk_id); + if (IS_ERR(clk) || !clk->name[0]) + return NULL; + + clkd =3D to_desc(clk); + /* Needs full enumeration ? */ + if (clkd->r.rate_discrete && clkd->tot_rates !=3D clkd->r.num_rates) { + int ret; + + /* rates[] is already allocated BUT we need to re-enumerate */ + clkd->r.num_rates =3D 0; + ret =3D scmi_clock_describe_rates_get_full(ph, clkd); + if (ret) + return NULL; + } + + return &clkd->r; +} + static int scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, enum clk_state state, @@ -1064,6 +1094,7 @@ static const struct scmi_clk_proto_ops clk_proto_ops = =3D { .rate_get =3D scmi_clock_rate_get, .rate_set =3D scmi_clock_rate_set, .determine_rate =3D scmi_clock_determine_rate, + .all_rates_get =3D scmi_clock_all_rates_get, .enable =3D scmi_clock_enable, .disable =3D scmi_clock_disable, .state_get =3D scmi_clock_state_get, diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 5552ac04c820..c710107c2120 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -40,6 +40,12 @@ struct scmi_revision_info { char sub_vendor_id[SCMI_SHORT_NAME_MAX_SIZE]; }; =20 +struct scmi_clock_rates { + bool rate_discrete; + unsigned int num_rates; + u64 *rates; +}; + struct scmi_clock_info { char name[SCMI_MAX_STR_SIZE]; unsigned int enable_latency; @@ -85,6 +91,7 @@ enum scmi_clock_oem_config { * clock calculating the closest allowed rate. * Note that @rate is an input/output parameter used both to * describe the requested rate and report the closest match + * @all_rates_get: get the list of all available rates for the specified c= lock. * @enable: enables the specified clock * @disable: disables the specified clock * @state_get: get the status of the specified clock @@ -104,6 +111,8 @@ struct scmi_clk_proto_ops { u64 rate); int (*determine_rate)(const struct scmi_protocol_handle *ph, u32 clk_id, unsigned long *rate); + const struct scmi_clock_rates __must_check *(*all_rates_get) + (const struct scmi_protocol_handle *ph, u32 clk_id); int (*enable)(const struct scmi_protocol_handle *ph, u32 clk_id, bool atomic); int (*disable)(const struct scmi_protocol_handle *ph, u32 clk_id, --=20 2.53.0