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