Skip to content

Commit 7bc7caa

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Use common iterators in the clock protocol
Make SCMI clock protocol use the common iterator protocol helpers for issuing the multi-part commands. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 802b0be commit 7bc7caa

File tree

1 file changed

+90
-60
lines changed

1 file changed

+90
-60
lines changed

drivers/firmware/arm_scmi/clock.c

Lines changed: 90 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -164,81 +164,111 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
164164
return 1;
165165
}
166166

167-
static int
168-
scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
169-
struct scmi_clock_info *clk)
170-
{
171-
u64 *rate = NULL;
172-
int ret, cnt;
173-
bool rate_discrete = false;
174-
u32 tot_rate_cnt = 0, rates_flag;
175-
u16 num_returned, num_remaining;
176-
struct scmi_xfer *t;
177-
struct scmi_msg_clock_describe_rates *clk_desc;
178-
struct scmi_msg_resp_clock_describe_rates *rlist;
167+
struct scmi_clk_ipriv {
168+
u32 clk_id;
169+
struct scmi_clock_info *clk;
170+
};
179171

180-
ret = ph->xops->xfer_get_init(ph, CLOCK_DESCRIBE_RATES,
181-
sizeof(*clk_desc), 0, &t);
182-
if (ret)
183-
return ret;
172+
static void iter_clk_describe_prepare_message(void *message,
173+
const unsigned int desc_index,
174+
const void *priv)
175+
{
176+
struct scmi_msg_clock_describe_rates *msg = message;
177+
const struct scmi_clk_ipriv *p = priv;
184178

185-
clk_desc = t->tx.buf;
186-
rlist = t->rx.buf;
179+
msg->id = cpu_to_le32(p->clk_id);
180+
/* Set the number of rates to be skipped/already read */
181+
msg->rate_index = cpu_to_le32(desc_index);
182+
}
187183

188-
do {
189-
clk_desc->id = cpu_to_le32(clk_id);
190-
/* Set the number of rates to be skipped/already read */
191-
clk_desc->rate_index = cpu_to_le32(tot_rate_cnt);
184+
static int
185+
iter_clk_describe_update_state(struct scmi_iterator_state *st,
186+
const void *response, void *priv)
187+
{
188+
u32 flags;
189+
struct scmi_clk_ipriv *p = priv;
190+
const struct scmi_msg_resp_clock_describe_rates *r = response;
192191

193-
ret = ph->xops->do_xfer(ph, t);
194-
if (ret)
195-
goto err;
192+
flags = le32_to_cpu(r->num_rates_flags);
193+
st->num_remaining = NUM_REMAINING(flags);
194+
st->num_returned = NUM_RETURNED(flags);
195+
p->clk->rate_discrete = RATE_DISCRETE(flags);
196196

197-
rates_flag = le32_to_cpu(rlist->num_rates_flags);
198-
num_remaining = NUM_REMAINING(rates_flag);
199-
rate_discrete = RATE_DISCRETE(rates_flag);
200-
num_returned = NUM_RETURNED(rates_flag);
197+
return 0;
198+
}
201199

202-
if (tot_rate_cnt + num_returned > SCMI_MAX_NUM_RATES) {
203-
dev_err(ph->dev, "No. of rates > MAX_NUM_RATES");
200+
static int
201+
iter_clk_describe_process_response(const struct scmi_protocol_handle *ph,
202+
const void *response,
203+
struct scmi_iterator_state *st, void *priv)
204+
{
205+
int ret = 0;
206+
struct scmi_clk_ipriv *p = priv;
207+
const struct scmi_msg_resp_clock_describe_rates *r = response;
208+
209+
if (!p->clk->rate_discrete) {
210+
switch (st->desc_index + st->loop_idx) {
211+
case 0:
212+
p->clk->range.min_rate = RATE_TO_U64(r->rate[0]);
204213
break;
205-
}
206-
207-
if (!rate_discrete) {
208-
clk->range.min_rate = RATE_TO_U64(rlist->rate[0]);
209-
clk->range.max_rate = RATE_TO_U64(rlist->rate[1]);
210-
clk->range.step_size = RATE_TO_U64(rlist->rate[2]);
211-
dev_dbg(ph->dev, "Min %llu Max %llu Step %llu Hz\n",
212-
clk->range.min_rate, clk->range.max_rate,
213-
clk->range.step_size);
214+
case 1:
215+
p->clk->range.max_rate = RATE_TO_U64(r->rate[1]);
216+
break;
217+
case 2:
218+
p->clk->range.step_size = RATE_TO_U64(r->rate[2]);
219+
break;
220+
default:
221+
ret = -EINVAL;
214222
break;
215223
}
224+
} else {
225+
u64 *rate = &p->clk->list.rates[st->desc_index + st->loop_idx];
216226

217-
rate = &clk->list.rates[tot_rate_cnt];
218-
for (cnt = 0; cnt < num_returned; cnt++, rate++) {
219-
*rate = RATE_TO_U64(rlist->rate[cnt]);
220-
dev_dbg(ph->dev, "Rate %llu Hz\n", *rate);
221-
}
227+
*rate = RATE_TO_U64(r->rate[st->loop_idx]);
228+
p->clk->list.num_rates++;
229+
//XXX dev_dbg(ph->dev, "Rate %llu Hz\n", *rate);
230+
}
231+
232+
return ret;
233+
}
222234

223-
tot_rate_cnt += num_returned;
235+
static int
236+
scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
237+
struct scmi_clock_info *clk)
238+
{
239+
int ret;
224240

225-
ph->xops->reset_rx_to_maxsz(ph, t);
226-
/*
227-
* check for both returned and remaining to avoid infinite
228-
* loop due to buggy firmware
229-
*/
230-
} while (num_returned && num_remaining);
241+
void *iter;
242+
struct scmi_msg_clock_describe_rates *msg;
243+
struct scmi_iterator_ops ops = {
244+
.prepare_message = iter_clk_describe_prepare_message,
245+
.update_state = iter_clk_describe_update_state,
246+
.process_response = iter_clk_describe_process_response,
247+
};
248+
struct scmi_clk_ipriv cpriv = {
249+
.clk_id = clk_id,
250+
.clk = clk,
251+
};
252+
253+
iter = ph->hops->iter_response_init(ph, &ops, SCMI_MAX_NUM_RATES,
254+
CLOCK_DESCRIBE_RATES,
255+
sizeof(*msg), &cpriv);
256+
if (IS_ERR(iter))
257+
return PTR_ERR(iter);
258+
259+
ret = ph->hops->iter_response_run(iter);
260+
if (ret)
261+
return ret;
231262

232-
if (rate_discrete && rate) {
233-
clk->list.num_rates = tot_rate_cnt;
234-
sort(clk->list.rates, tot_rate_cnt, sizeof(*rate),
235-
rate_cmp_func, NULL);
263+
if (!clk->rate_discrete) {
264+
dev_dbg(ph->dev, "Min %llu Max %llu Step %llu Hz\n",
265+
clk->range.min_rate, clk->range.max_rate,
266+
clk->range.step_size);
267+
} else if (clk->list.num_rates) {
268+
sort(clk->list.rates, clk->list.num_rates,
269+
sizeof(clk->list.rates[0]), rate_cmp_func, NULL);
236270
}
237271

238-
clk->rate_discrete = rate_discrete;
239-
240-
err:
241-
ph->xops->xfer_put(ph, t);
242272
return ret;
243273
}
244274

0 commit comments

Comments
 (0)