diff options
-rw-r--r-- | drivers/firmware/arm_scmi/clock.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index dd215bd11a58..4a32ae1822a3 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -56,7 +56,7 @@ struct scmi_msg_resp_clock_describe_rates { struct scmi_clock_set_rate { __le32 flags; #define CLOCK_SET_ASYNC BIT(0) -#define CLOCK_SET_DELAYED BIT(1) +#define CLOCK_SET_IGNORE_RESP BIT(1) #define CLOCK_SET_ROUND_UP BIT(2) #define CLOCK_SET_ROUND_AUTO BIT(3) __le32 id; @@ -67,6 +67,7 @@ struct scmi_clock_set_rate { struct clock_info { int num_clocks; int max_async_req; + atomic_t cur_async_req; struct scmi_clock_info *clk; }; @@ -221,21 +222,33 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, u64 rate) { int ret; + u32 flags = 0; struct scmi_xfer *t; struct scmi_clock_set_rate *cfg; + struct clock_info *ci = handle->clk_priv; ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, sizeof(*cfg), 0, &t); if (ret) return ret; + if (ci->max_async_req && + atomic_inc_return(&ci->cur_async_req) < ci->max_async_req) + flags |= CLOCK_SET_ASYNC; + cfg = t->tx.buf; - cfg->flags = cpu_to_le32(0); + cfg->flags = cpu_to_le32(flags); cfg->id = cpu_to_le32(clk_id); cfg->value_low = cpu_to_le32(rate & 0xffffffff); cfg->value_high = cpu_to_le32(rate >> 32); - ret = scmi_do_xfer(handle, t); + if (flags & CLOCK_SET_ASYNC) + ret = scmi_do_xfer_with_response(handle, t); + else + ret = scmi_do_xfer(handle, t); + + if (ci->max_async_req) + atomic_dec(&ci->cur_async_req); scmi_xfer_put(handle, t); return ret; |