mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 06:57:30 -04:00
firmware: arm_scmi: Add clock determine_rate operation
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 simplifications 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 <cristian.marussi@arm.com> Tested-by: Florian Fainelli <florian.fainelli@broadcom.com> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://patch.msgid.link/20260508153300.2224715-3-cristian.marussi@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
This commit is contained in:
committed by
Sudeep Holla
parent
d0c81a38d0
commit
ecde921eb4
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2018-2022 ARM Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/sort.h>
|
||||
@@ -624,6 +625,46 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 = ph->get_priv(ph);
|
||||
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
clk = 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 = clk->range.min_rate;
|
||||
fmax = clk->range.max_rate;
|
||||
if (*rate <= fmin) {
|
||||
*rate = fmin;
|
||||
return 0;
|
||||
} else if (*rate >= fmax) {
|
||||
*rate = fmax;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ftmp = *rate - fmin;
|
||||
ftmp += clk->range.step_size - 1; /* to round up */
|
||||
ftmp = div64_ul(ftmp, clk->range.step_size);
|
||||
|
||||
*rate = 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 = {
|
||||
.info_get = scmi_clock_info_get,
|
||||
.rate_get = scmi_clock_rate_get,
|
||||
.rate_set = scmi_clock_rate_set,
|
||||
.determine_rate = scmi_clock_determine_rate,
|
||||
.enable = scmi_clock_enable,
|
||||
.disable = scmi_clock_disable,
|
||||
.state_get = scmi_clock_state_get,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user