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