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