xref: /rk3399_ARM-atf/drivers/scmi-msg/clock.c (revision 958e071f68f3422c18acb969fb19813026cf9d9c)
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
17*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_get_enable_delay
18b4734308SPeng Fan #pragma weak plat_scmi_clock_rates_array
19b4734308SPeng Fan #pragma weak plat_scmi_clock_rates_by_step
20*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_get_possible_parents
21*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_get_parent
22*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_set_parent
23b4734308SPeng Fan #pragma weak plat_scmi_clock_get_rate
24b4734308SPeng Fan #pragma weak plat_scmi_clock_set_rate
25b4734308SPeng Fan #pragma weak plat_scmi_clock_get_state
26b4734308SPeng Fan #pragma weak plat_scmi_clock_set_state
27*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_get_extended_config
28*684952d1SKamlesh Gurudasani #pragma weak plat_scmi_clock_set_extended_config
29b4734308SPeng Fan 
30b4734308SPeng Fan static bool message_id_is_supported(unsigned int message_id);
31b4734308SPeng Fan 
plat_scmi_clock_count(unsigned int agent_id __unused)32b4734308SPeng Fan size_t plat_scmi_clock_count(unsigned int agent_id __unused)
33b4734308SPeng Fan {
34b4734308SPeng Fan 	return 0U;
35b4734308SPeng Fan }
36b4734308SPeng Fan 
plat_scmi_clock_get_name(unsigned int agent_id __unused,unsigned int scmi_id __unused)37b4734308SPeng Fan const char *plat_scmi_clock_get_name(unsigned int agent_id __unused,
38b4734308SPeng Fan 				     unsigned int scmi_id __unused)
39b4734308SPeng Fan {
40b4734308SPeng Fan 	return NULL;
41b4734308SPeng Fan }
42b4734308SPeng Fan 
plat_scmi_clock_get_enable_delay(unsigned int agent_id __unused,unsigned int scmi_id __unused)43*684952d1SKamlesh Gurudasani uint32_t plat_scmi_clock_get_enable_delay(unsigned int agent_id __unused,
44*684952d1SKamlesh Gurudasani 					  unsigned int scmi_id __unused)
45*684952d1SKamlesh Gurudasani {
46*684952d1SKamlesh Gurudasani 	return 0U;
47*684952d1SKamlesh Gurudasani }
48*684952d1SKamlesh Gurudasani 
plat_scmi_clock_rates_array(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long * rates __unused,size_t * nb_elts __unused,uint32_t start_idx __unused)49b4734308SPeng Fan int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused,
50b4734308SPeng Fan 				    unsigned int scmi_id __unused,
51b4734308SPeng Fan 				    unsigned long *rates __unused,
52ca9d6edcSXiaoDong Huang 				    size_t *nb_elts __unused,
53ca9d6edcSXiaoDong Huang 				    uint32_t start_idx __unused)
54b4734308SPeng Fan {
55b4734308SPeng Fan 	return SCMI_NOT_SUPPORTED;
56b4734308SPeng Fan }
57b4734308SPeng Fan 
plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long * steps __unused)58b4734308SPeng Fan int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
59b4734308SPeng Fan 				      unsigned int scmi_id __unused,
60b4734308SPeng Fan 				      unsigned long *steps __unused)
61b4734308SPeng Fan {
62b4734308SPeng Fan 	return SCMI_NOT_SUPPORTED;
63b4734308SPeng Fan }
64b4734308SPeng Fan 
plat_scmi_clock_get_possible_parents(unsigned int agent_id,unsigned int scmi_id,unsigned int * plat_possible_parents,size_t * nb_elts,unsigned int skip_parents)65*684952d1SKamlesh Gurudasani int32_t plat_scmi_clock_get_possible_parents(unsigned int agent_id,
66*684952d1SKamlesh Gurudasani 					     unsigned int scmi_id,
67*684952d1SKamlesh Gurudasani 					     unsigned int *plat_possible_parents,
68*684952d1SKamlesh Gurudasani 					     size_t *nb_elts,
69*684952d1SKamlesh Gurudasani 					     unsigned int skip_parents)
70*684952d1SKamlesh Gurudasani {
71*684952d1SKamlesh Gurudasani 	return SCMI_NOT_SUPPORTED;
72*684952d1SKamlesh Gurudasani }
73*684952d1SKamlesh Gurudasani 
plat_scmi_clock_get_parent(unsigned int agent_id,unsigned int scmi_id,unsigned int * parent_id)74*684952d1SKamlesh Gurudasani int32_t plat_scmi_clock_get_parent(unsigned int agent_id,
75*684952d1SKamlesh Gurudasani 				   unsigned int scmi_id,
76*684952d1SKamlesh Gurudasani 				   unsigned int *parent_id)
77*684952d1SKamlesh Gurudasani {
78*684952d1SKamlesh Gurudasani 	return SCMI_NOT_SUPPORTED;
79*684952d1SKamlesh Gurudasani }
80*684952d1SKamlesh Gurudasani 
plat_scmi_clock_set_parent(unsigned int agent_id,unsigned int scmi_id,unsigned int parent_id)81*684952d1SKamlesh Gurudasani int32_t plat_scmi_clock_set_parent(unsigned int agent_id,
82*684952d1SKamlesh Gurudasani 				   unsigned int scmi_id,
83*684952d1SKamlesh Gurudasani 				   unsigned int parent_id)
84*684952d1SKamlesh Gurudasani {
85*684952d1SKamlesh Gurudasani 	return SCMI_NOT_SUPPORTED;
86*684952d1SKamlesh Gurudasani }
87*684952d1SKamlesh Gurudasani 
plat_scmi_clock_get_rate(unsigned int agent_id __unused,unsigned int scmi_id __unused)88b4734308SPeng Fan unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused,
89b4734308SPeng Fan 				       unsigned int scmi_id __unused)
90b4734308SPeng Fan {
91b4734308SPeng Fan 	return 0U;
92b4734308SPeng Fan }
93b4734308SPeng Fan 
plat_scmi_clock_set_rate(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned long rate __unused)94b4734308SPeng Fan int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused,
95b4734308SPeng Fan 				 unsigned int scmi_id __unused,
96b4734308SPeng Fan 				 unsigned long rate __unused)
97b4734308SPeng Fan {
98b4734308SPeng Fan 	return SCMI_NOT_SUPPORTED;
99b4734308SPeng Fan }
100b4734308SPeng Fan 
plat_scmi_clock_get_state(unsigned int agent_id __unused,unsigned int scmi_id __unused)101b4734308SPeng Fan int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused,
102b4734308SPeng Fan 				  unsigned int scmi_id __unused)
103b4734308SPeng Fan {
104b4734308SPeng Fan 	return SCMI_NOT_SUPPORTED;
105b4734308SPeng Fan }
106b4734308SPeng Fan 
plat_scmi_clock_set_state(unsigned int agent_id __unused,unsigned int scmi_id __unused,bool enable_not_disable __unused)107b4734308SPeng Fan int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused,
108b4734308SPeng Fan 				  unsigned int scmi_id __unused,
109b4734308SPeng Fan 				  bool enable_not_disable __unused)
110b4734308SPeng Fan {
111b4734308SPeng Fan 	return SCMI_NOT_SUPPORTED;
112b4734308SPeng Fan }
113b4734308SPeng Fan 
plat_scmi_clock_get_extended_config(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned char extended_config_type __unused,unsigned int * extended_config_val __unused)114*684952d1SKamlesh Gurudasani int32_t plat_scmi_clock_get_extended_config(unsigned int agent_id __unused,
115*684952d1SKamlesh Gurudasani 					    unsigned int scmi_id __unused,
116*684952d1SKamlesh Gurudasani 					    unsigned char extended_config_type __unused,
117*684952d1SKamlesh Gurudasani 					    unsigned int *extended_config_val __unused)
118*684952d1SKamlesh Gurudasani {
119*684952d1SKamlesh Gurudasani 	return SCMI_NOT_SUPPORTED;
120*684952d1SKamlesh Gurudasani }
121*684952d1SKamlesh Gurudasani 
plat_scmi_clock_set_extended_config(unsigned int agent_id __unused,unsigned int scmi_id __unused,unsigned char extended_config_type __unused,unsigned int extended_config_val __unused)122*684952d1SKamlesh Gurudasani int32_t plat_scmi_clock_set_extended_config(unsigned int agent_id __unused,
123*684952d1SKamlesh Gurudasani 					    unsigned int scmi_id __unused,
124*684952d1SKamlesh Gurudasani 					    unsigned char extended_config_type __unused,
125*684952d1SKamlesh Gurudasani 					    unsigned int extended_config_val __unused)
126*684952d1SKamlesh Gurudasani {
127*684952d1SKamlesh Gurudasani 	return SCMI_NOT_SUPPORTED;
128*684952d1SKamlesh Gurudasani }
129*684952d1SKamlesh Gurudasani 
report_version(struct scmi_msg * msg)130b4734308SPeng Fan static void report_version(struct scmi_msg *msg)
131b4734308SPeng Fan {
132b4734308SPeng Fan 	struct scmi_protocol_version_p2a return_values = {
133b4734308SPeng Fan 		.status = SCMI_SUCCESS,
134b4734308SPeng Fan 		.version = SCMI_PROTOCOL_VERSION_CLOCK,
135b4734308SPeng Fan 	};
136b4734308SPeng Fan 
137b4734308SPeng Fan 	if (msg->in_size != 0) {
138b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
139b4734308SPeng Fan 		return;
140b4734308SPeng Fan 	}
141b4734308SPeng Fan 
142b4734308SPeng Fan 	scmi_write_response(msg, &return_values, sizeof(return_values));
143b4734308SPeng Fan }
144b4734308SPeng Fan 
report_attributes(struct scmi_msg * msg)145b4734308SPeng Fan static void report_attributes(struct scmi_msg *msg)
146b4734308SPeng Fan {
147b4734308SPeng Fan 	size_t agent_count = plat_scmi_clock_count(msg->agent_id);
148b4734308SPeng Fan 	struct scmi_protocol_attributes_p2a return_values = {
149b4734308SPeng Fan 		.status = SCMI_SUCCESS,
150b4734308SPeng Fan 		.attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count),
151b4734308SPeng Fan 	};
152b4734308SPeng Fan 
153b4734308SPeng Fan 	if (msg->in_size != 0) {
154b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
155b4734308SPeng Fan 		return;
156b4734308SPeng Fan 	}
157b4734308SPeng Fan 
158b4734308SPeng Fan 	scmi_write_response(msg, &return_values, sizeof(return_values));
159b4734308SPeng Fan }
160b4734308SPeng Fan 
report_message_attributes(struct scmi_msg * msg)161b4734308SPeng Fan static void report_message_attributes(struct scmi_msg *msg)
162b4734308SPeng Fan {
163b4734308SPeng Fan 	struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
164b4734308SPeng Fan 	struct scmi_protocol_message_attributes_p2a return_values = {
165b4734308SPeng Fan 		.status = SCMI_SUCCESS,
166b4734308SPeng Fan 		/* For this protocol, attributes shall be zero */
167b4734308SPeng Fan 		.attributes = 0U,
168b4734308SPeng Fan 	};
169b4734308SPeng Fan 
170b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
171b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
172b4734308SPeng Fan 		return;
173b4734308SPeng Fan 	}
174b4734308SPeng Fan 
175b4734308SPeng Fan 	if (!message_id_is_supported(in_args->message_id)) {
176b4734308SPeng Fan 		scmi_status_response(msg, SCMI_NOT_FOUND);
177b4734308SPeng Fan 		return;
178b4734308SPeng Fan 	}
179b4734308SPeng Fan 
180b4734308SPeng Fan 	scmi_write_response(msg, &return_values, sizeof(return_values));
181b4734308SPeng Fan }
182b4734308SPeng Fan 
scmi_clock_attributes(struct scmi_msg * msg)183b4734308SPeng Fan static void scmi_clock_attributes(struct scmi_msg *msg)
184b4734308SPeng Fan {
185b4734308SPeng Fan 	const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in;
186b4734308SPeng Fan 	struct scmi_clock_attributes_p2a return_values = {
187b4734308SPeng Fan 		.status = SCMI_SUCCESS,
188b4734308SPeng Fan 	};
189b4734308SPeng Fan 	const char *name = NULL;
190b4734308SPeng Fan 	unsigned int clock_id = 0U;
191b4734308SPeng Fan 
192b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
193b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
194b4734308SPeng Fan 		return;
195b4734308SPeng Fan 	}
196b4734308SPeng Fan 
197b4734308SPeng Fan 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
198b4734308SPeng Fan 
199b4734308SPeng Fan 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
20048ec8d33Sscaria 		scmi_status_response(msg, SCMI_NOT_FOUND);
201b4734308SPeng Fan 		return;
202b4734308SPeng Fan 	}
203b4734308SPeng Fan 
204b4734308SPeng Fan 
205b4734308SPeng Fan 	name = plat_scmi_clock_get_name(msg->agent_id, clock_id);
206b4734308SPeng Fan 	if (name == NULL) {
207b4734308SPeng Fan 		scmi_status_response(msg, SCMI_NOT_FOUND);
208b4734308SPeng Fan 		return;
209b4734308SPeng Fan 	}
210b4734308SPeng Fan 
211b4734308SPeng Fan 	COPY_NAME_IDENTIFIER(return_values.clock_name, name);
212b4734308SPeng Fan 
213b4734308SPeng Fan 	return_values.attributes = plat_scmi_clock_get_state(msg->agent_id,
214b4734308SPeng Fan 							     clock_id);
215b4734308SPeng Fan 
216*684952d1SKamlesh Gurudasani 	return_values.attributes |= BIT(SCMI_CLOCK_EXTENDED_CONFIG_SUPPORT_POS);
217*684952d1SKamlesh Gurudasani 	return_values.attributes |= BIT(SCMI_CLOCK_PARENT_IDENTIFIER_SUPPORT_POS);
218*684952d1SKamlesh Gurudasani 
219*684952d1SKamlesh Gurudasani 	return_values.clock_enable_delay = plat_scmi_clock_get_enable_delay(msg->agent_id,
220*684952d1SKamlesh Gurudasani 									    clock_id);
221*684952d1SKamlesh Gurudasani 
222b4734308SPeng Fan 	scmi_write_response(msg, &return_values, sizeof(return_values));
223b4734308SPeng Fan }
224b4734308SPeng Fan 
225*684952d1SKamlesh Gurudasani 
226*684952d1SKamlesh Gurudasani 
227*684952d1SKamlesh Gurudasani #define PARENTS_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \
228*684952d1SKamlesh Gurudasani 				sizeof(struct scmi_clock_possible_parents_get_p2a))
229*684952d1SKamlesh Gurudasani 
230*684952d1SKamlesh Gurudasani /* Protocol limits the maximum number of parent clock identifiers that are
231*684952d1SKamlesh Gurudasani  * remaining or returned by this call
232*684952d1SKamlesh Gurudasani  */
233*684952d1SKamlesh Gurudasani #define PARENT_CLOCK_MAX_COUNT				255U
234*684952d1SKamlesh Gurudasani 
235*684952d1SKamlesh Gurudasani #define PARENT_CLOCK_IDENTIFIER_SIZE			sizeof(uint32_t)
236*684952d1SKamlesh Gurudasani 
237*684952d1SKamlesh Gurudasani #define PARENTS_ARRAY_ELEMENTS_NUMBER_MAX		((uint32_t)(PARENTS_ARRAY_SIZE_MAX / \
238*684952d1SKamlesh Gurudasani 							 PARENT_CLOCK_IDENTIFIER_SIZE))
239*684952d1SKamlesh Gurudasani 
write_possible_parents_array_in_buffer(char * dest,unsigned int * possible_parents,size_t nb_elt)240*684952d1SKamlesh Gurudasani static void write_possible_parents_array_in_buffer(char *dest, unsigned int *possible_parents,
241*684952d1SKamlesh Gurudasani 						   size_t nb_elt)
242*684952d1SKamlesh Gurudasani {
243*684952d1SKamlesh Gurudasani 	uint32_t *out = (uint32_t *)(uintptr_t)dest;
244*684952d1SKamlesh Gurudasani 	size_t n;
245*684952d1SKamlesh Gurudasani 
246*684952d1SKamlesh Gurudasani 	ASSERT_SYM_PTR_ALIGN(out);
247*684952d1SKamlesh Gurudasani 
248*684952d1SKamlesh Gurudasani 	for (n = 0U; n < nb_elt; n++) {
249*684952d1SKamlesh Gurudasani 		out[n] = (uint32_t)possible_parents[n];
250*684952d1SKamlesh Gurudasani 	}
251*684952d1SKamlesh Gurudasani }
252*684952d1SKamlesh Gurudasani 
scmi_clock_possible_parents_get(struct scmi_msg * msg)253*684952d1SKamlesh Gurudasani static void scmi_clock_possible_parents_get(struct scmi_msg *msg)
254*684952d1SKamlesh Gurudasani {
255*684952d1SKamlesh Gurudasani 	const struct scmi_clock_possible_parents_get_a2p *in_args = (void *)msg->in;
256*684952d1SKamlesh Gurudasani 	struct scmi_clock_possible_parents_get_p2a p2a = {
257*684952d1SKamlesh Gurudasani 		.status = SCMI_SUCCESS,
258*684952d1SKamlesh Gurudasani 		.flags = 0,
259*684952d1SKamlesh Gurudasani 	};
260*684952d1SKamlesh Gurudasani 
261*684952d1SKamlesh Gurudasani 	unsigned int clock_id = 0U;
262*684952d1SKamlesh Gurudasani 	size_t nb_possible_parents;
263*684952d1SKamlesh Gurudasani 	int32_t status;
264*684952d1SKamlesh Gurudasani 
265*684952d1SKamlesh Gurudasani 	if (msg->in_size != sizeof(*in_args)) {
266*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
267*684952d1SKamlesh Gurudasani 		return;
268*684952d1SKamlesh Gurudasani 	}
269*684952d1SKamlesh Gurudasani 
270*684952d1SKamlesh Gurudasani 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
271*684952d1SKamlesh Gurudasani 
272*684952d1SKamlesh Gurudasani 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
273*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_NOT_FOUND);
274*684952d1SKamlesh Gurudasani 		return;
275*684952d1SKamlesh Gurudasani 	}
276*684952d1SKamlesh Gurudasani 	/* Get number of possible parents */
277*684952d1SKamlesh Gurudasani 	status = plat_scmi_clock_get_possible_parents(msg->agent_id, clock_id, NULL,
278*684952d1SKamlesh Gurudasani 						      &nb_possible_parents, 0);
279*684952d1SKamlesh Gurudasani 	if (status == SCMI_SUCCESS) {
280*684952d1SKamlesh Gurudasani 
281*684952d1SKamlesh Gurudasani 		if (in_args->skip_parents >= nb_possible_parents) {
282*684952d1SKamlesh Gurudasani 			scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
283*684952d1SKamlesh Gurudasani 			return;
284*684952d1SKamlesh Gurudasani 		}
285*684952d1SKamlesh Gurudasani 
286*684952d1SKamlesh Gurudasani 		/* Currently 20 cells max, so it's affordable for the stack */
287*684952d1SKamlesh Gurudasani 		unsigned int plat_possible_parents[PARENTS_ARRAY_ELEMENTS_NUMBER_MAX];
288*684952d1SKamlesh Gurudasani 		size_t max_nb = MIN(PARENTS_ARRAY_ELEMENTS_NUMBER_MAX,
289*684952d1SKamlesh Gurudasani 				    PARENT_CLOCK_MAX_COUNT);
290*684952d1SKamlesh Gurudasani 		size_t ret_nb = MIN(nb_possible_parents - in_args->skip_parents, max_nb);
291*684952d1SKamlesh Gurudasani 		size_t rem_nb = nb_possible_parents - in_args->skip_parents - ret_nb;
292*684952d1SKamlesh Gurudasani 
293*684952d1SKamlesh Gurudasani 		rem_nb = MIN((uint32_t)rem_nb, PARENT_CLOCK_MAX_COUNT);
294*684952d1SKamlesh Gurudasani 
295*684952d1SKamlesh Gurudasani 		status =  plat_scmi_clock_get_possible_parents(msg->agent_id, clock_id,
296*684952d1SKamlesh Gurudasani 							       plat_possible_parents, &ret_nb,
297*684952d1SKamlesh Gurudasani 							       in_args->skip_parents);
298*684952d1SKamlesh Gurudasani 		if (status == SCMI_SUCCESS) {
299*684952d1SKamlesh Gurudasani 			ret_nb = MIN(ret_nb, max_nb);
300*684952d1SKamlesh Gurudasani 			write_possible_parents_array_in_buffer(msg->out + sizeof(p2a),
301*684952d1SKamlesh Gurudasani 							       plat_possible_parents, ret_nb);
302*684952d1SKamlesh Gurudasani 
303*684952d1SKamlesh Gurudasani 			p2a.flags = ((uint8_t)rem_nb) << 24;
304*684952d1SKamlesh Gurudasani 			p2a.flags |= (uint8_t)ret_nb;
305*684952d1SKamlesh Gurudasani 			p2a.status = SCMI_SUCCESS;
306*684952d1SKamlesh Gurudasani 
307*684952d1SKamlesh Gurudasani 			memcpy(msg->out, &p2a, sizeof(p2a));
308*684952d1SKamlesh Gurudasani 			msg->out_size_out = sizeof(p2a) +
309*684952d1SKamlesh Gurudasani 					    ret_nb * sizeof(unsigned int);
310*684952d1SKamlesh Gurudasani 		}
311*684952d1SKamlesh Gurudasani 
312*684952d1SKamlesh Gurudasani 	} else {
313*684952d1SKamlesh Gurudasani 		/* Fallthrough generic exit sequence below with error status */
314*684952d1SKamlesh Gurudasani 	}
315*684952d1SKamlesh Gurudasani 
316*684952d1SKamlesh Gurudasani 	if (status != SCMI_SUCCESS) {
317*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, status);
318*684952d1SKamlesh Gurudasani 	} else {
319*684952d1SKamlesh Gurudasani 		/*
320*684952d1SKamlesh Gurudasani 		 * Message payload is already written to msg->out, and
321*684952d1SKamlesh Gurudasani 		 * msg->out_size_out updated.
322*684952d1SKamlesh Gurudasani 		 */
323*684952d1SKamlesh Gurudasani 	}
324*684952d1SKamlesh Gurudasani }
325*684952d1SKamlesh Gurudasani 
scmi_clock_parent_get(struct scmi_msg * msg)326*684952d1SKamlesh Gurudasani static void scmi_clock_parent_get(struct scmi_msg *msg)
327*684952d1SKamlesh Gurudasani {
328*684952d1SKamlesh Gurudasani 	const struct scmi_clock_parent_get_a2p *in_args = (void *)msg->in;
329*684952d1SKamlesh Gurudasani 
330*684952d1SKamlesh Gurudasani 	struct scmi_clock_parent_get_p2a return_values = {
331*684952d1SKamlesh Gurudasani 		.status = SCMI_SUCCESS,
332*684952d1SKamlesh Gurudasani 	};
333*684952d1SKamlesh Gurudasani 	unsigned int clock_id = 0U;
334*684952d1SKamlesh Gurudasani 
335*684952d1SKamlesh Gurudasani 	if (msg->in_size != sizeof(*in_args)) {
336*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
337*684952d1SKamlesh Gurudasani 		return;
338*684952d1SKamlesh Gurudasani 	}
339*684952d1SKamlesh Gurudasani 
340*684952d1SKamlesh Gurudasani 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
341*684952d1SKamlesh Gurudasani 
342*684952d1SKamlesh Gurudasani 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
343*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_NOT_FOUND);
344*684952d1SKamlesh Gurudasani 		return;
345*684952d1SKamlesh Gurudasani 	}
346*684952d1SKamlesh Gurudasani 
347*684952d1SKamlesh Gurudasani 	return_values.status = plat_scmi_clock_get_parent(msg->agent_id, clock_id,
348*684952d1SKamlesh Gurudasani 							  &return_values.parent_id);
349*684952d1SKamlesh Gurudasani 
350*684952d1SKamlesh Gurudasani 	scmi_write_response(msg, &return_values, sizeof(return_values));
351*684952d1SKamlesh Gurudasani }
352*684952d1SKamlesh Gurudasani 
scmi_clock_parent_set(struct scmi_msg * msg)353*684952d1SKamlesh Gurudasani static void scmi_clock_parent_set(struct scmi_msg *msg)
354*684952d1SKamlesh Gurudasani {
355*684952d1SKamlesh Gurudasani 	const struct scmi_clock_parent_set_a2p *in_args = (void *)msg->in;
356*684952d1SKamlesh Gurudasani 
357*684952d1SKamlesh Gurudasani 	int32_t status = 0;
358*684952d1SKamlesh Gurudasani 	unsigned int clock_id = 0U;
359*684952d1SKamlesh Gurudasani 	unsigned int parent_id = 0U;
360*684952d1SKamlesh Gurudasani 	unsigned int clock_count = 0U;
361*684952d1SKamlesh Gurudasani 
362*684952d1SKamlesh Gurudasani 	if (msg->in_size != sizeof(*in_args)) {
363*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
364*684952d1SKamlesh Gurudasani 		return;
365*684952d1SKamlesh Gurudasani 	}
366*684952d1SKamlesh Gurudasani 
367*684952d1SKamlesh Gurudasani 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
368*684952d1SKamlesh Gurudasani 	parent_id = SPECULATION_SAFE_VALUE(in_args->parent_id);
369*684952d1SKamlesh Gurudasani 
370*684952d1SKamlesh Gurudasani 	clock_count = plat_scmi_clock_count(msg->agent_id);
371*684952d1SKamlesh Gurudasani 	if (clock_id >= clock_count || parent_id >= clock_count) {
372*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_NOT_FOUND);
373*684952d1SKamlesh Gurudasani 		return;
374*684952d1SKamlesh Gurudasani 	}
375*684952d1SKamlesh Gurudasani 
376*684952d1SKamlesh Gurudasani 	status = plat_scmi_clock_set_parent(msg->agent_id, clock_id, parent_id);
377*684952d1SKamlesh Gurudasani 
378*684952d1SKamlesh Gurudasani 	scmi_status_response(msg, status);
379*684952d1SKamlesh Gurudasani }
380*684952d1SKamlesh Gurudasani 
scmi_clock_rate_get(struct scmi_msg * msg)381b4734308SPeng Fan static void scmi_clock_rate_get(struct scmi_msg *msg)
382b4734308SPeng Fan {
383b4734308SPeng Fan 	const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in;
384b4734308SPeng Fan 	unsigned long rate = 0U;
385b4734308SPeng Fan 	struct scmi_clock_rate_get_p2a return_values = {
386b4734308SPeng Fan 		.status = SCMI_SUCCESS,
387b4734308SPeng Fan 	};
388b4734308SPeng Fan 	unsigned int clock_id = 0U;
389b4734308SPeng Fan 
390b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
391b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
392b4734308SPeng Fan 		return;
393b4734308SPeng Fan 	}
394b4734308SPeng Fan 
395b4734308SPeng Fan 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
396b4734308SPeng Fan 
397b4734308SPeng Fan 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
39848ec8d33Sscaria 		scmi_status_response(msg, SCMI_NOT_FOUND);
399b4734308SPeng Fan 		return;
400b4734308SPeng Fan 	}
401b4734308SPeng Fan 
402b4734308SPeng Fan 	rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id);
403b4734308SPeng Fan 
404b4734308SPeng Fan 	return_values.rate[0] = (uint32_t)rate;
405b4734308SPeng Fan 	return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32);
406b4734308SPeng Fan 
407b4734308SPeng Fan 	scmi_write_response(msg, &return_values, sizeof(return_values));
408b4734308SPeng Fan }
409b4734308SPeng Fan 
scmi_clock_rate_set(struct scmi_msg * msg)410b4734308SPeng Fan static void scmi_clock_rate_set(struct scmi_msg *msg)
411b4734308SPeng Fan {
412b4734308SPeng Fan 	const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in;
413b4734308SPeng Fan 	unsigned long rate = 0U;
414b4734308SPeng Fan 	int32_t status = 0;
415b4734308SPeng Fan 	unsigned int clock_id = 0U;
416b4734308SPeng Fan 
417b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
418b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
419b4734308SPeng Fan 		return;
420b4734308SPeng Fan 	}
421b4734308SPeng Fan 
422b4734308SPeng Fan 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
423b4734308SPeng Fan 
424b4734308SPeng Fan 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
42548ec8d33Sscaria 		scmi_status_response(msg, SCMI_NOT_FOUND);
426b4734308SPeng Fan 		return;
427b4734308SPeng Fan 	}
428b4734308SPeng Fan 
429b4734308SPeng Fan 	rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) |
430b4734308SPeng Fan 			       in_args->rate[0]);
431b4734308SPeng Fan 
432b4734308SPeng Fan 	status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate);
433b4734308SPeng Fan 
434b4734308SPeng Fan 	scmi_status_response(msg, status);
435b4734308SPeng Fan }
436b4734308SPeng Fan 
scmi_clock_config_get(struct scmi_msg * msg)437*684952d1SKamlesh Gurudasani static void scmi_clock_config_get(struct scmi_msg *msg)
438*684952d1SKamlesh Gurudasani {
439*684952d1SKamlesh Gurudasani 	const struct scmi_clock_config_get_a2p *in_args = (void *)msg->in;
440*684952d1SKamlesh Gurudasani 	struct scmi_clock_config_get_p2a p2a = {
441*684952d1SKamlesh Gurudasani 		.status = SCMI_SUCCESS,
442*684952d1SKamlesh Gurudasani 	};
443*684952d1SKamlesh Gurudasani 	unsigned int extended_config_type = 0U;
444*684952d1SKamlesh Gurudasani 	unsigned int clock_id = 0U;
445*684952d1SKamlesh Gurudasani 
446*684952d1SKamlesh Gurudasani 	if (msg->in_size != sizeof(*in_args)) {
447*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
448*684952d1SKamlesh Gurudasani 		return;
449*684952d1SKamlesh Gurudasani 	}
450*684952d1SKamlesh Gurudasani 
451*684952d1SKamlesh Gurudasani 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
452*684952d1SKamlesh Gurudasani 
453*684952d1SKamlesh Gurudasani 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
454*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_NOT_FOUND);
455*684952d1SKamlesh Gurudasani 		return;
456*684952d1SKamlesh Gurudasani 	}
457*684952d1SKamlesh Gurudasani 
458*684952d1SKamlesh Gurudasani 	p2a.config = plat_scmi_clock_get_state(msg->agent_id, clock_id);
459*684952d1SKamlesh Gurudasani 
460*684952d1SKamlesh Gurudasani 	extended_config_type = in_args->flags & SCMI_CLOCK_EXTENDED_CONFIG_GET_TYPE_MASK;
461*684952d1SKamlesh Gurudasani 	if (extended_config_type != 0U) {
462*684952d1SKamlesh Gurudasani 		p2a.status = plat_scmi_clock_get_extended_config(msg->agent_id,
463*684952d1SKamlesh Gurudasani 								 clock_id,
464*684952d1SKamlesh Gurudasani 								 extended_config_type,
465*684952d1SKamlesh Gurudasani 								 &p2a.extended_config_val);
466*684952d1SKamlesh Gurudasani 	}
467*684952d1SKamlesh Gurudasani 
468*684952d1SKamlesh Gurudasani 	scmi_write_response(msg, &p2a, sizeof(p2a));
469*684952d1SKamlesh Gurudasani }
470*684952d1SKamlesh Gurudasani 
scmi_clock_config_set(struct scmi_msg * msg)471b4734308SPeng Fan static void scmi_clock_config_set(struct scmi_msg *msg)
472b4734308SPeng Fan {
473b4734308SPeng Fan 	const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in;
474b4734308SPeng Fan 	int32_t status = SCMI_GENERIC_ERROR;
475*684952d1SKamlesh Gurudasani 	uint8_t enable = 0U;
476b4734308SPeng Fan 	unsigned int clock_id = 0U;
477*684952d1SKamlesh Gurudasani 	uint8_t extended_config_type = 0U;
478b4734308SPeng Fan 
479b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
480b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
481b4734308SPeng Fan 		return;
482b4734308SPeng Fan 	}
483b4734308SPeng Fan 
484b4734308SPeng Fan 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
485b4734308SPeng Fan 
486b4734308SPeng Fan 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
48748ec8d33Sscaria 		scmi_status_response(msg, SCMI_NOT_FOUND);
488b4734308SPeng Fan 		return;
489b4734308SPeng Fan 	}
490b4734308SPeng Fan 
491b4734308SPeng Fan 	enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK;
492b4734308SPeng Fan 
493*684952d1SKamlesh Gurudasani 	extended_config_type = in_args->attributes & SCMI_CLOCK_EXTENDED_CONFIG_SET_TYPE_MASK;
494*684952d1SKamlesh Gurudasani 
495*684952d1SKamlesh Gurudasani 	if ((extended_config_type == 0U)
496*684952d1SKamlesh Gurudasani 	    && (enable == SCMI_CLOCK_CONFIG_SET_UNCHANGED_STATE)) {
497*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
498*684952d1SKamlesh Gurudasani 		return;
499*684952d1SKamlesh Gurudasani 	}
500*684952d1SKamlesh Gurudasani 
501*684952d1SKamlesh Gurudasani 	if (enable == SCMI_CLOCK_CONFIG_SET_RESERVED_STATE) {
502*684952d1SKamlesh Gurudasani 		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
503*684952d1SKamlesh Gurudasani 		return;
504*684952d1SKamlesh Gurudasani 	}
505*684952d1SKamlesh Gurudasani 
506*684952d1SKamlesh Gurudasani 	if (enable != SCMI_CLOCK_CONFIG_SET_UNCHANGED_STATE) {
507*684952d1SKamlesh Gurudasani 		status = plat_scmi_clock_set_state(msg->agent_id, clock_id, (bool)enable);
508*684952d1SKamlesh Gurudasani 		if (status != SCMI_SUCCESS) {
509*684952d1SKamlesh Gurudasani 			scmi_status_response(msg, status);
510*684952d1SKamlesh Gurudasani 			return;
511*684952d1SKamlesh Gurudasani 		}
512*684952d1SKamlesh Gurudasani 	}
513*684952d1SKamlesh Gurudasani 
514*684952d1SKamlesh Gurudasani 	if (extended_config_type != 0U) {
515*684952d1SKamlesh Gurudasani 		status = plat_scmi_clock_set_extended_config(msg->agent_id, clock_id,
516*684952d1SKamlesh Gurudasani 							     extended_config_type,
517*684952d1SKamlesh Gurudasani 							     in_args->extended_config_val);
518*684952d1SKamlesh Gurudasani 	}
519b4734308SPeng Fan 
520b4734308SPeng Fan 	scmi_status_response(msg, status);
521b4734308SPeng Fan }
522b4734308SPeng Fan 
523b4734308SPeng Fan #define RATES_ARRAY_SIZE_MAX	(SCMI_PLAYLOAD_MAX - \
524b4734308SPeng Fan 				 sizeof(struct scmi_clock_describe_rates_p2a))
525b4734308SPeng Fan 
526b4734308SPeng Fan #define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \
527b4734308SPeng Fan 	SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \
528b4734308SPeng Fan 						SCMI_CLOCK_RATE_FORMAT_LIST, \
529b4734308SPeng Fan 						(_rem_rates))
530b4734308SPeng Fan #define SCMI_RATES_BY_STEP \
531b4734308SPeng Fan 	SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \
532b4734308SPeng Fan 						SCMI_CLOCK_RATE_FORMAT_RANGE, \
533b4734308SPeng Fan 						0U)
534b4734308SPeng Fan 
535b4734308SPeng Fan #define RATE_DESC_SIZE		sizeof(struct scmi_clock_rate)
536b4734308SPeng Fan 
write_rate_desc_array_in_buffer(char * dest,unsigned long * rates,size_t nb_elt)537b4734308SPeng Fan static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates,
538b4734308SPeng Fan 					    size_t nb_elt)
539b4734308SPeng Fan {
540b4734308SPeng Fan 	uint32_t *out = (uint32_t *)(uintptr_t)dest;
541b4734308SPeng Fan 	size_t n;
542b4734308SPeng Fan 
543b4734308SPeng Fan 	ASSERT_SYM_PTR_ALIGN(out);
544b4734308SPeng Fan 
545b4734308SPeng Fan 	for (n = 0U; n < nb_elt; n++) {
546b4734308SPeng Fan 		out[2 * n] = (uint32_t)rates[n];
547b4734308SPeng Fan 		out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32);
548b4734308SPeng Fan 	}
549b4734308SPeng Fan }
550b4734308SPeng Fan 
scmi_clock_describe_rates(struct scmi_msg * msg)551b4734308SPeng Fan static void scmi_clock_describe_rates(struct scmi_msg *msg)
552b4734308SPeng Fan {
553b4734308SPeng Fan 	const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in;
554b4734308SPeng Fan 	struct scmi_clock_describe_rates_p2a p2a = {
555b4734308SPeng Fan 		.status = SCMI_SUCCESS,
556b4734308SPeng Fan 	};
557b4734308SPeng Fan 	size_t nb_rates;
558b4734308SPeng Fan 	int32_t status;
559b4734308SPeng Fan 	unsigned int clock_id;
560b4734308SPeng Fan 
561b4734308SPeng Fan 	if (msg->in_size != sizeof(*in_args)) {
562b4734308SPeng Fan 		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
563b4734308SPeng Fan 		return;
564b4734308SPeng Fan 	}
565b4734308SPeng Fan 
566b4734308SPeng Fan 	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
567b4734308SPeng Fan 
568b4734308SPeng Fan 	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
56948ec8d33Sscaria 		scmi_status_response(msg, SCMI_NOT_FOUND);
570b4734308SPeng Fan 		return;
571b4734308SPeng Fan 	}
572b4734308SPeng Fan 
573b4734308SPeng Fan 	/* Platform may support array rate description */
574b4734308SPeng Fan 	status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL,
575ca9d6edcSXiaoDong Huang 					     &nb_rates, 0);
576b4734308SPeng Fan 	if (status == SCMI_SUCCESS) {
577b4734308SPeng Fan 		/* Currently 12 cells mex, so it's affordable for the stack */
578b4734308SPeng Fan 		unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE];
579b4734308SPeng Fan 		size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE;
580b4734308SPeng Fan 		size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb);
581b4734308SPeng Fan 		size_t rem_nb = nb_rates - in_args->rate_index - ret_nb;
582b4734308SPeng Fan 
583b4734308SPeng Fan 		status =  plat_scmi_clock_rates_array(msg->agent_id, clock_id,
584ca9d6edcSXiaoDong Huang 						      plat_rates, &ret_nb,
585ca9d6edcSXiaoDong Huang 						      in_args->rate_index);
586b4734308SPeng Fan 		if (status == SCMI_SUCCESS) {
587b4734308SPeng Fan 			write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
588b4734308SPeng Fan 							plat_rates, ret_nb);
589b4734308SPeng Fan 
590b4734308SPeng Fan 			p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb,
591b4734308SPeng Fan 								  rem_nb);
592b4734308SPeng Fan 			p2a.status = SCMI_SUCCESS;
593b4734308SPeng Fan 
594b4734308SPeng Fan 			memcpy(msg->out, &p2a, sizeof(p2a));
595b4734308SPeng Fan 			msg->out_size_out = sizeof(p2a) +
596b4734308SPeng Fan 					    ret_nb * RATE_DESC_SIZE;
597b4734308SPeng Fan 		}
598b4734308SPeng Fan 	} else if (status == SCMI_NOT_SUPPORTED) {
599b4734308SPeng Fan 		unsigned long triplet[3] = { 0U, 0U, 0U };
600b4734308SPeng Fan 
601b4734308SPeng Fan 		/* Platform may support min§max/step triplet description */
602b4734308SPeng Fan 		status =  plat_scmi_clock_rates_by_step(msg->agent_id, clock_id,
603b4734308SPeng Fan 							triplet);
604b4734308SPeng Fan 		if (status == SCMI_SUCCESS) {
605b4734308SPeng Fan 			write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
606b4734308SPeng Fan 							triplet, 3U);
607b4734308SPeng Fan 
608b4734308SPeng Fan 			p2a.num_rates_flags = SCMI_RATES_BY_STEP;
609b4734308SPeng Fan 			p2a.status = SCMI_SUCCESS;
610b4734308SPeng Fan 
611b4734308SPeng Fan 			memcpy(msg->out, &p2a, sizeof(p2a));
612b4734308SPeng Fan 			msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE);
613b4734308SPeng Fan 		}
614b4734308SPeng Fan 	} else {
615b4734308SPeng Fan 		/* Fallthrough generic exit sequence below with error status */
616b4734308SPeng Fan 	}
617b4734308SPeng Fan 
618b4734308SPeng Fan 	if (status != SCMI_SUCCESS) {
619b4734308SPeng Fan 		scmi_status_response(msg, status);
620b4734308SPeng Fan 	} else {
621b4734308SPeng Fan 		/*
6221b491eeaSElyes Haouas 		 * Message payload is already written to msg->out, and
623b4734308SPeng Fan 		 * msg->out_size_out updated.
624b4734308SPeng Fan 		 */
625b4734308SPeng Fan 	}
626b4734308SPeng Fan }
627b4734308SPeng Fan 
628b4734308SPeng Fan static const scmi_msg_handler_t scmi_clock_handler_table[] = {
629b4734308SPeng Fan 	[SCMI_PROTOCOL_VERSION] = report_version,
630b4734308SPeng Fan 	[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
631b4734308SPeng Fan 	[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
632b4734308SPeng Fan 	[SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes,
633b4734308SPeng Fan 	[SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates,
634b4734308SPeng Fan 	[SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set,
635b4734308SPeng Fan 	[SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get,
636b4734308SPeng Fan 	[SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set,
637*684952d1SKamlesh Gurudasani 	[SCMI_CLOCK_CONFIG_GET] = scmi_clock_config_get,
638*684952d1SKamlesh Gurudasani 	[SCMI_CLOCK_POSSIBLE_PARENTS_GET] = scmi_clock_possible_parents_get,
639*684952d1SKamlesh Gurudasani 	[SCMI_CLOCK_PARENT_SET] = scmi_clock_parent_set,
640*684952d1SKamlesh Gurudasani 	[SCMI_CLOCK_PARENT_GET] = scmi_clock_parent_get,
641b4734308SPeng Fan };
642b4734308SPeng Fan 
message_id_is_supported(unsigned int message_id)6432355ebffSSchspa Shi static bool message_id_is_supported(unsigned int message_id)
644b4734308SPeng Fan {
645b4734308SPeng Fan 	return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) &&
646b4734308SPeng Fan 	       (scmi_clock_handler_table[message_id] != NULL);
647b4734308SPeng Fan }
648b4734308SPeng Fan 
scmi_msg_get_clock_handler(struct scmi_msg * msg)649b4734308SPeng Fan scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg)
650b4734308SPeng Fan {
651b4734308SPeng Fan 	const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table);
652b4734308SPeng Fan 	unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
653b4734308SPeng Fan 
654b4734308SPeng Fan 	if (message_id >= array_size) {
655b4734308SPeng Fan 		VERBOSE("Clock handle not found %u", msg->message_id);
656b4734308SPeng Fan 		return NULL;
657b4734308SPeng Fan 	}
658b4734308SPeng Fan 
659b4734308SPeng Fan 	return scmi_clock_handler_table[message_id];
660b4734308SPeng Fan }
661