1*54fd6939SJiyong Park // SPDX-License-Identifier: BSD-3-Clause
2*54fd6939SJiyong Park /*
3*54fd6939SJiyong Park * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
4*54fd6939SJiyong Park * Copyright (c) 2019-2020, Linaro Limited
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park #include <cdefs.h>
7*54fd6939SJiyong Park #include <string.h>
8*54fd6939SJiyong Park
9*54fd6939SJiyong Park #include <drivers/scmi-msg.h>
10*54fd6939SJiyong Park #include <drivers/scmi.h>
11*54fd6939SJiyong Park #include <lib/utils_def.h>
12*54fd6939SJiyong Park
13*54fd6939SJiyong Park #include "common.h"
14*54fd6939SJiyong Park
15*54fd6939SJiyong Park #pragma weak plat_scmi_clock_count
16*54fd6939SJiyong Park #pragma weak plat_scmi_clock_get_name
17*54fd6939SJiyong Park #pragma weak plat_scmi_clock_rates_array
18*54fd6939SJiyong Park #pragma weak plat_scmi_clock_rates_by_step
19*54fd6939SJiyong Park #pragma weak plat_scmi_clock_get_rate
20*54fd6939SJiyong Park #pragma weak plat_scmi_clock_set_rate
21*54fd6939SJiyong Park #pragma weak plat_scmi_clock_get_state
22*54fd6939SJiyong Park #pragma weak plat_scmi_clock_set_state
23*54fd6939SJiyong Park
24*54fd6939SJiyong Park static bool message_id_is_supported(unsigned int message_id);
25*54fd6939SJiyong Park
plat_scmi_clock_count(unsigned int agent_id __unused)26*54fd6939SJiyong Park size_t plat_scmi_clock_count(unsigned int agent_id __unused)
27*54fd6939SJiyong Park {
28*54fd6939SJiyong Park return 0U;
29*54fd6939SJiyong Park }
30*54fd6939SJiyong Park
plat_scmi_clock_get_name(unsigned int agent_id __unused,unsigned int scmi_id __unused)31*54fd6939SJiyong Park const char *plat_scmi_clock_get_name(unsigned int agent_id __unused,
32*54fd6939SJiyong Park unsigned int scmi_id __unused)
33*54fd6939SJiyong Park {
34*54fd6939SJiyong Park return NULL;
35*54fd6939SJiyong Park }
36*54fd6939SJiyong Park
plat_scmi_clock_rates_array(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long * rates __unused,size_t * nb_elts __unused)37*54fd6939SJiyong Park int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused,
38*54fd6939SJiyong Park unsigned int scmi_id __unused,
39*54fd6939SJiyong Park unsigned long *rates __unused,
40*54fd6939SJiyong Park size_t *nb_elts __unused)
41*54fd6939SJiyong Park {
42*54fd6939SJiyong Park return SCMI_NOT_SUPPORTED;
43*54fd6939SJiyong Park }
44*54fd6939SJiyong Park
plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long * steps __unused)45*54fd6939SJiyong Park int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
46*54fd6939SJiyong Park unsigned int scmi_id __unused,
47*54fd6939SJiyong Park unsigned long *steps __unused)
48*54fd6939SJiyong Park {
49*54fd6939SJiyong Park return SCMI_NOT_SUPPORTED;
50*54fd6939SJiyong Park }
51*54fd6939SJiyong Park
plat_scmi_clock_get_rate(unsigned int agent_id __unused,unsigned int scmi_id __unused)52*54fd6939SJiyong Park unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused,
53*54fd6939SJiyong Park unsigned int scmi_id __unused)
54*54fd6939SJiyong Park {
55*54fd6939SJiyong Park return 0U;
56*54fd6939SJiyong Park }
57*54fd6939SJiyong Park
plat_scmi_clock_set_rate(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long rate __unused)58*54fd6939SJiyong Park int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused,
59*54fd6939SJiyong Park unsigned int scmi_id __unused,
60*54fd6939SJiyong Park unsigned long rate __unused)
61*54fd6939SJiyong Park {
62*54fd6939SJiyong Park return SCMI_NOT_SUPPORTED;
63*54fd6939SJiyong Park }
64*54fd6939SJiyong Park
plat_scmi_clock_get_state(unsigned int agent_id __unused,unsigned int scmi_id __unused)65*54fd6939SJiyong Park int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused,
66*54fd6939SJiyong Park unsigned int scmi_id __unused)
67*54fd6939SJiyong Park {
68*54fd6939SJiyong Park return SCMI_NOT_SUPPORTED;
69*54fd6939SJiyong Park }
70*54fd6939SJiyong Park
plat_scmi_clock_set_state(unsigned int agent_id __unused,unsigned int scmi_id __unused,bool enable_not_disable __unused)71*54fd6939SJiyong Park int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused,
72*54fd6939SJiyong Park unsigned int scmi_id __unused,
73*54fd6939SJiyong Park bool enable_not_disable __unused)
74*54fd6939SJiyong Park {
75*54fd6939SJiyong Park return SCMI_NOT_SUPPORTED;
76*54fd6939SJiyong Park }
77*54fd6939SJiyong Park
report_version(struct scmi_msg * msg)78*54fd6939SJiyong Park static void report_version(struct scmi_msg *msg)
79*54fd6939SJiyong Park {
80*54fd6939SJiyong Park struct scmi_protocol_version_p2a return_values = {
81*54fd6939SJiyong Park .status = SCMI_SUCCESS,
82*54fd6939SJiyong Park .version = SCMI_PROTOCOL_VERSION_CLOCK,
83*54fd6939SJiyong Park };
84*54fd6939SJiyong Park
85*54fd6939SJiyong Park if (msg->in_size != 0) {
86*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
87*54fd6939SJiyong Park return;
88*54fd6939SJiyong Park }
89*54fd6939SJiyong Park
90*54fd6939SJiyong Park scmi_write_response(msg, &return_values, sizeof(return_values));
91*54fd6939SJiyong Park }
92*54fd6939SJiyong Park
report_attributes(struct scmi_msg * msg)93*54fd6939SJiyong Park static void report_attributes(struct scmi_msg *msg)
94*54fd6939SJiyong Park {
95*54fd6939SJiyong Park size_t agent_count = plat_scmi_clock_count(msg->agent_id);
96*54fd6939SJiyong Park struct scmi_protocol_attributes_p2a return_values = {
97*54fd6939SJiyong Park .status = SCMI_SUCCESS,
98*54fd6939SJiyong Park .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count),
99*54fd6939SJiyong Park };
100*54fd6939SJiyong Park
101*54fd6939SJiyong Park if (msg->in_size != 0) {
102*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
103*54fd6939SJiyong Park return;
104*54fd6939SJiyong Park }
105*54fd6939SJiyong Park
106*54fd6939SJiyong Park scmi_write_response(msg, &return_values, sizeof(return_values));
107*54fd6939SJiyong Park }
108*54fd6939SJiyong Park
report_message_attributes(struct scmi_msg * msg)109*54fd6939SJiyong Park static void report_message_attributes(struct scmi_msg *msg)
110*54fd6939SJiyong Park {
111*54fd6939SJiyong Park struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
112*54fd6939SJiyong Park struct scmi_protocol_message_attributes_p2a return_values = {
113*54fd6939SJiyong Park .status = SCMI_SUCCESS,
114*54fd6939SJiyong Park /* For this protocol, attributes shall be zero */
115*54fd6939SJiyong Park .attributes = 0U,
116*54fd6939SJiyong Park };
117*54fd6939SJiyong Park
118*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
119*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
120*54fd6939SJiyong Park return;
121*54fd6939SJiyong Park }
122*54fd6939SJiyong Park
123*54fd6939SJiyong Park if (!message_id_is_supported(in_args->message_id)) {
124*54fd6939SJiyong Park scmi_status_response(msg, SCMI_NOT_FOUND);
125*54fd6939SJiyong Park return;
126*54fd6939SJiyong Park }
127*54fd6939SJiyong Park
128*54fd6939SJiyong Park scmi_write_response(msg, &return_values, sizeof(return_values));
129*54fd6939SJiyong Park }
130*54fd6939SJiyong Park
scmi_clock_attributes(struct scmi_msg * msg)131*54fd6939SJiyong Park static void scmi_clock_attributes(struct scmi_msg *msg)
132*54fd6939SJiyong Park {
133*54fd6939SJiyong Park const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in;
134*54fd6939SJiyong Park struct scmi_clock_attributes_p2a return_values = {
135*54fd6939SJiyong Park .status = SCMI_SUCCESS,
136*54fd6939SJiyong Park };
137*54fd6939SJiyong Park const char *name = NULL;
138*54fd6939SJiyong Park unsigned int clock_id = 0U;
139*54fd6939SJiyong Park
140*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
141*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
142*54fd6939SJiyong Park return;
143*54fd6939SJiyong Park }
144*54fd6939SJiyong Park
145*54fd6939SJiyong Park clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
146*54fd6939SJiyong Park
147*54fd6939SJiyong Park if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
148*54fd6939SJiyong Park scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
149*54fd6939SJiyong Park return;
150*54fd6939SJiyong Park }
151*54fd6939SJiyong Park
152*54fd6939SJiyong Park
153*54fd6939SJiyong Park name = plat_scmi_clock_get_name(msg->agent_id, clock_id);
154*54fd6939SJiyong Park if (name == NULL) {
155*54fd6939SJiyong Park scmi_status_response(msg, SCMI_NOT_FOUND);
156*54fd6939SJiyong Park return;
157*54fd6939SJiyong Park }
158*54fd6939SJiyong Park
159*54fd6939SJiyong Park COPY_NAME_IDENTIFIER(return_values.clock_name, name);
160*54fd6939SJiyong Park
161*54fd6939SJiyong Park return_values.attributes = plat_scmi_clock_get_state(msg->agent_id,
162*54fd6939SJiyong Park clock_id);
163*54fd6939SJiyong Park
164*54fd6939SJiyong Park scmi_write_response(msg, &return_values, sizeof(return_values));
165*54fd6939SJiyong Park }
166*54fd6939SJiyong Park
scmi_clock_rate_get(struct scmi_msg * msg)167*54fd6939SJiyong Park static void scmi_clock_rate_get(struct scmi_msg *msg)
168*54fd6939SJiyong Park {
169*54fd6939SJiyong Park const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in;
170*54fd6939SJiyong Park unsigned long rate = 0U;
171*54fd6939SJiyong Park struct scmi_clock_rate_get_p2a return_values = {
172*54fd6939SJiyong Park .status = SCMI_SUCCESS,
173*54fd6939SJiyong Park };
174*54fd6939SJiyong Park unsigned int clock_id = 0U;
175*54fd6939SJiyong Park
176*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
177*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
178*54fd6939SJiyong Park return;
179*54fd6939SJiyong Park }
180*54fd6939SJiyong Park
181*54fd6939SJiyong Park clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
182*54fd6939SJiyong Park
183*54fd6939SJiyong Park if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
184*54fd6939SJiyong Park scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
185*54fd6939SJiyong Park return;
186*54fd6939SJiyong Park }
187*54fd6939SJiyong Park
188*54fd6939SJiyong Park rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id);
189*54fd6939SJiyong Park
190*54fd6939SJiyong Park return_values.rate[0] = (uint32_t)rate;
191*54fd6939SJiyong Park return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32);
192*54fd6939SJiyong Park
193*54fd6939SJiyong Park scmi_write_response(msg, &return_values, sizeof(return_values));
194*54fd6939SJiyong Park }
195*54fd6939SJiyong Park
scmi_clock_rate_set(struct scmi_msg * msg)196*54fd6939SJiyong Park static void scmi_clock_rate_set(struct scmi_msg *msg)
197*54fd6939SJiyong Park {
198*54fd6939SJiyong Park const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in;
199*54fd6939SJiyong Park unsigned long rate = 0U;
200*54fd6939SJiyong Park int32_t status = 0;
201*54fd6939SJiyong Park unsigned int clock_id = 0U;
202*54fd6939SJiyong Park
203*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
204*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
205*54fd6939SJiyong Park return;
206*54fd6939SJiyong Park }
207*54fd6939SJiyong Park
208*54fd6939SJiyong Park clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
209*54fd6939SJiyong Park
210*54fd6939SJiyong Park if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
211*54fd6939SJiyong Park scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
212*54fd6939SJiyong Park return;
213*54fd6939SJiyong Park }
214*54fd6939SJiyong Park
215*54fd6939SJiyong Park rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) |
216*54fd6939SJiyong Park in_args->rate[0]);
217*54fd6939SJiyong Park
218*54fd6939SJiyong Park status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate);
219*54fd6939SJiyong Park
220*54fd6939SJiyong Park scmi_status_response(msg, status);
221*54fd6939SJiyong Park }
222*54fd6939SJiyong Park
scmi_clock_config_set(struct scmi_msg * msg)223*54fd6939SJiyong Park static void scmi_clock_config_set(struct scmi_msg *msg)
224*54fd6939SJiyong Park {
225*54fd6939SJiyong Park const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in;
226*54fd6939SJiyong Park int32_t status = SCMI_GENERIC_ERROR;
227*54fd6939SJiyong Park bool enable = false;
228*54fd6939SJiyong Park unsigned int clock_id = 0U;
229*54fd6939SJiyong Park
230*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
231*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
232*54fd6939SJiyong Park return;
233*54fd6939SJiyong Park }
234*54fd6939SJiyong Park
235*54fd6939SJiyong Park clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
236*54fd6939SJiyong Park
237*54fd6939SJiyong Park if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
238*54fd6939SJiyong Park scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
239*54fd6939SJiyong Park return;
240*54fd6939SJiyong Park }
241*54fd6939SJiyong Park
242*54fd6939SJiyong Park enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK;
243*54fd6939SJiyong Park
244*54fd6939SJiyong Park status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable);
245*54fd6939SJiyong Park
246*54fd6939SJiyong Park scmi_status_response(msg, status);
247*54fd6939SJiyong Park }
248*54fd6939SJiyong Park
249*54fd6939SJiyong Park #define RATES_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \
250*54fd6939SJiyong Park sizeof(struct scmi_clock_describe_rates_p2a))
251*54fd6939SJiyong Park
252*54fd6939SJiyong Park #define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \
253*54fd6939SJiyong Park SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \
254*54fd6939SJiyong Park SCMI_CLOCK_RATE_FORMAT_LIST, \
255*54fd6939SJiyong Park (_rem_rates))
256*54fd6939SJiyong Park #define SCMI_RATES_BY_STEP \
257*54fd6939SJiyong Park SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \
258*54fd6939SJiyong Park SCMI_CLOCK_RATE_FORMAT_RANGE, \
259*54fd6939SJiyong Park 0U)
260*54fd6939SJiyong Park
261*54fd6939SJiyong Park #define RATE_DESC_SIZE sizeof(struct scmi_clock_rate)
262*54fd6939SJiyong Park
write_rate_desc_array_in_buffer(char * dest,unsigned long * rates,size_t nb_elt)263*54fd6939SJiyong Park static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates,
264*54fd6939SJiyong Park size_t nb_elt)
265*54fd6939SJiyong Park {
266*54fd6939SJiyong Park uint32_t *out = (uint32_t *)(uintptr_t)dest;
267*54fd6939SJiyong Park size_t n;
268*54fd6939SJiyong Park
269*54fd6939SJiyong Park ASSERT_SYM_PTR_ALIGN(out);
270*54fd6939SJiyong Park
271*54fd6939SJiyong Park for (n = 0U; n < nb_elt; n++) {
272*54fd6939SJiyong Park out[2 * n] = (uint32_t)rates[n];
273*54fd6939SJiyong Park out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32);
274*54fd6939SJiyong Park }
275*54fd6939SJiyong Park }
276*54fd6939SJiyong Park
scmi_clock_describe_rates(struct scmi_msg * msg)277*54fd6939SJiyong Park static void scmi_clock_describe_rates(struct scmi_msg *msg)
278*54fd6939SJiyong Park {
279*54fd6939SJiyong Park const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in;
280*54fd6939SJiyong Park struct scmi_clock_describe_rates_p2a p2a = {
281*54fd6939SJiyong Park .status = SCMI_SUCCESS,
282*54fd6939SJiyong Park };
283*54fd6939SJiyong Park size_t nb_rates;
284*54fd6939SJiyong Park int32_t status;
285*54fd6939SJiyong Park unsigned int clock_id;
286*54fd6939SJiyong Park
287*54fd6939SJiyong Park if (msg->in_size != sizeof(*in_args)) {
288*54fd6939SJiyong Park scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
289*54fd6939SJiyong Park return;
290*54fd6939SJiyong Park }
291*54fd6939SJiyong Park
292*54fd6939SJiyong Park clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
293*54fd6939SJiyong Park
294*54fd6939SJiyong Park if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
295*54fd6939SJiyong Park scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
296*54fd6939SJiyong Park return;
297*54fd6939SJiyong Park }
298*54fd6939SJiyong Park
299*54fd6939SJiyong Park /* Platform may support array rate description */
300*54fd6939SJiyong Park status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL,
301*54fd6939SJiyong Park &nb_rates);
302*54fd6939SJiyong Park if (status == SCMI_SUCCESS) {
303*54fd6939SJiyong Park /* Currently 12 cells mex, so it's affordable for the stack */
304*54fd6939SJiyong Park unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE];
305*54fd6939SJiyong Park size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE;
306*54fd6939SJiyong Park size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb);
307*54fd6939SJiyong Park size_t rem_nb = nb_rates - in_args->rate_index - ret_nb;
308*54fd6939SJiyong Park
309*54fd6939SJiyong Park status = plat_scmi_clock_rates_array(msg->agent_id, clock_id,
310*54fd6939SJiyong Park plat_rates, &ret_nb);
311*54fd6939SJiyong Park if (status == SCMI_SUCCESS) {
312*54fd6939SJiyong Park write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
313*54fd6939SJiyong Park plat_rates, ret_nb);
314*54fd6939SJiyong Park
315*54fd6939SJiyong Park p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb,
316*54fd6939SJiyong Park rem_nb);
317*54fd6939SJiyong Park p2a.status = SCMI_SUCCESS;
318*54fd6939SJiyong Park
319*54fd6939SJiyong Park memcpy(msg->out, &p2a, sizeof(p2a));
320*54fd6939SJiyong Park msg->out_size_out = sizeof(p2a) +
321*54fd6939SJiyong Park ret_nb * RATE_DESC_SIZE;
322*54fd6939SJiyong Park }
323*54fd6939SJiyong Park } else if (status == SCMI_NOT_SUPPORTED) {
324*54fd6939SJiyong Park unsigned long triplet[3] = { 0U, 0U, 0U };
325*54fd6939SJiyong Park
326*54fd6939SJiyong Park /* Platform may support min§max/step triplet description */
327*54fd6939SJiyong Park status = plat_scmi_clock_rates_by_step(msg->agent_id, clock_id,
328*54fd6939SJiyong Park triplet);
329*54fd6939SJiyong Park if (status == SCMI_SUCCESS) {
330*54fd6939SJiyong Park write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
331*54fd6939SJiyong Park triplet, 3U);
332*54fd6939SJiyong Park
333*54fd6939SJiyong Park p2a.num_rates_flags = SCMI_RATES_BY_STEP;
334*54fd6939SJiyong Park p2a.status = SCMI_SUCCESS;
335*54fd6939SJiyong Park
336*54fd6939SJiyong Park memcpy(msg->out, &p2a, sizeof(p2a));
337*54fd6939SJiyong Park msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE);
338*54fd6939SJiyong Park }
339*54fd6939SJiyong Park } else {
340*54fd6939SJiyong Park /* Fallthrough generic exit sequence below with error status */
341*54fd6939SJiyong Park }
342*54fd6939SJiyong Park
343*54fd6939SJiyong Park if (status != SCMI_SUCCESS) {
344*54fd6939SJiyong Park scmi_status_response(msg, status);
345*54fd6939SJiyong Park } else {
346*54fd6939SJiyong Park /*
347*54fd6939SJiyong Park * Message payload is already writen to msg->out, and
348*54fd6939SJiyong Park * msg->out_size_out updated.
349*54fd6939SJiyong Park */
350*54fd6939SJiyong Park }
351*54fd6939SJiyong Park }
352*54fd6939SJiyong Park
353*54fd6939SJiyong Park static const scmi_msg_handler_t scmi_clock_handler_table[] = {
354*54fd6939SJiyong Park [SCMI_PROTOCOL_VERSION] = report_version,
355*54fd6939SJiyong Park [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
356*54fd6939SJiyong Park [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
357*54fd6939SJiyong Park [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes,
358*54fd6939SJiyong Park [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates,
359*54fd6939SJiyong Park [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set,
360*54fd6939SJiyong Park [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get,
361*54fd6939SJiyong Park [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set,
362*54fd6939SJiyong Park };
363*54fd6939SJiyong Park
message_id_is_supported(size_t message_id)364*54fd6939SJiyong Park static bool message_id_is_supported(size_t message_id)
365*54fd6939SJiyong Park {
366*54fd6939SJiyong Park return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) &&
367*54fd6939SJiyong Park (scmi_clock_handler_table[message_id] != NULL);
368*54fd6939SJiyong Park }
369*54fd6939SJiyong Park
scmi_msg_get_clock_handler(struct scmi_msg * msg)370*54fd6939SJiyong Park scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg)
371*54fd6939SJiyong Park {
372*54fd6939SJiyong Park const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table);
373*54fd6939SJiyong Park unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
374*54fd6939SJiyong Park
375*54fd6939SJiyong Park if (message_id >= array_size) {
376*54fd6939SJiyong Park VERBOSE("Clock handle not found %u", msg->message_id);
377*54fd6939SJiyong Park return NULL;
378*54fd6939SJiyong Park }
379*54fd6939SJiyong Park
380*54fd6939SJiyong Park return scmi_clock_handler_table[message_id];
381*54fd6939SJiyong Park }
382