1 /*
2  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*!
8  * File containing client-side RPC functions for the PM service. These
9  * functions are ported to clients that communicate to the SC.
10  *
11  * @addtogroup PM_SVC
12  * @{
13  */
14 
15 /* Includes */
16 
17 #include <stdlib.h>
18 
19 #include <sci/sci_types.h>
20 #include <sci/svc/rm/sci_rm_api.h>
21 #include <sci/svc/pm/sci_pm_api.h>
22 #include <sci/sci_rpc.h>
23 
24 #include "sci_pm_rpc.h"
25 
26 /* Local Defines */
27 
28 /* Local Types */
29 
30 /* Local Functions */
31 
sc_pm_set_sys_power_mode(sc_ipc_t ipc,sc_pm_power_mode_t mode)32 sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode)
33 {
34 	sc_rpc_msg_t msg;
35 	uint8_t result;
36 
37 	RPC_VER(&msg) = SC_RPC_VERSION;
38 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
39 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_SYS_POWER_MODE;
40 	RPC_U8(&msg, 0U) = (uint8_t)mode;
41 	RPC_SIZE(&msg) = 2U;
42 
43 	sc_call_rpc(ipc, &msg, SC_FALSE);
44 
45 	result = RPC_R8(&msg);
46 	return (sc_err_t)result;
47 }
48 
sc_pm_set_partition_power_mode(sc_ipc_t ipc,sc_rm_pt_t pt,sc_pm_power_mode_t mode)49 sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
50 					sc_pm_power_mode_t mode)
51 {
52 	sc_rpc_msg_t msg;
53 	uint8_t result;
54 
55 	RPC_VER(&msg) = SC_RPC_VERSION;
56 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
57 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_PARTITION_POWER_MODE;
58 	RPC_U8(&msg, 0U) = (uint8_t)pt;
59 	RPC_U8(&msg, 1U) = (uint8_t)mode;
60 	RPC_SIZE(&msg) = 2U;
61 
62 	sc_call_rpc(ipc, &msg, SC_FALSE);
63 
64 	result = RPC_R8(&msg);
65 	return (sc_err_t)result;
66 }
67 
sc_pm_get_sys_power_mode(sc_ipc_t ipc,sc_rm_pt_t pt,sc_pm_power_mode_t * mode)68 sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
69 				  sc_pm_power_mode_t *mode)
70 {
71 	sc_rpc_msg_t msg;
72 	uint8_t result;
73 
74 	RPC_VER(&msg) = SC_RPC_VERSION;
75 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
76 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_SYS_POWER_MODE;
77 	RPC_U8(&msg, 0U) = (uint8_t)pt;
78 	RPC_SIZE(&msg) = 2U;
79 
80 	sc_call_rpc(ipc, &msg, SC_FALSE);
81 
82 	result = RPC_R8(&msg);
83 	if (mode != NULL) {
84 		*mode = RPC_U8(&msg, 0U);
85 	}
86 
87 	return (sc_err_t)result;
88 }
89 
sc_pm_set_resource_power_mode(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_power_mode_t mode)90 sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
91 				       sc_pm_power_mode_t mode)
92 {
93 	sc_rpc_msg_t msg;
94 	uint8_t result;
95 
96 	RPC_VER(&msg) = SC_RPC_VERSION;
97 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
98 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_RESOURCE_POWER_MODE;
99 	RPC_U16(&msg, 0U) = (uint16_t)resource;
100 	RPC_U8(&msg, 2U) = (uint8_t)mode;
101 	RPC_SIZE(&msg) = 2U;
102 
103 	sc_call_rpc(ipc, &msg, SC_FALSE);
104 
105 	result = RPC_R8(&msg);
106 	return (sc_err_t)result;
107 }
108 
sc_pm_get_resource_power_mode(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_power_mode_t * mode)109 sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
110 				       sc_pm_power_mode_t *mode)
111 {
112 	sc_rpc_msg_t msg;
113 	uint8_t result;
114 
115 	RPC_VER(&msg) = SC_RPC_VERSION;
116 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
117 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_RESOURCE_POWER_MODE;
118 	RPC_U16(&msg, 0U) = (uint16_t)resource;
119 	RPC_SIZE(&msg) = 2U;
120 
121 	sc_call_rpc(ipc, &msg, SC_FALSE);
122 
123 	result = RPC_R8(&msg);
124 	if (mode != NULL) {
125 		*mode = RPC_U8(&msg, 0U);
126 	}
127 
128 	return (sc_err_t)result;
129 }
130 
sc_pm_req_low_power_mode(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_power_mode_t mode)131 sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
132 				  sc_pm_power_mode_t mode)
133 {
134 	sc_rpc_msg_t msg;
135 	uint8_t result;
136 
137 	RPC_VER(&msg) = SC_RPC_VERSION;
138 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
139 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_LOW_POWER_MODE;
140 	RPC_U16(&msg, 0U) = (uint16_t)resource;
141 	RPC_U8(&msg, 2U) = (uint8_t)mode;
142 	RPC_SIZE(&msg) = 2U;
143 
144 	sc_call_rpc(ipc, &msg, SC_FALSE);
145 
146 	result = RPC_R8(&msg);
147 	return (sc_err_t)result;
148 }
149 
sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_power_mode_t mode,sc_pm_wake_src_t wake_src)150 sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
151 				      sc_pm_power_mode_t mode,
152 				      sc_pm_wake_src_t wake_src)
153 {
154 	sc_rpc_msg_t msg;
155 	uint8_t result;
156 
157 	RPC_VER(&msg) = SC_RPC_VERSION;
158 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
159 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_CPU_LOW_POWER_MODE;
160 	RPC_U16(&msg, 0U) = (uint16_t)resource;
161 	RPC_U8(&msg, 2U) = (uint8_t)mode;
162 	RPC_U8(&msg, 3U) = (uint8_t)wake_src;
163 	RPC_SIZE(&msg) = 2U;
164 
165 	sc_call_rpc(ipc, &msg, SC_FALSE);
166 
167 	result = RPC_R8(&msg);
168 	return (sc_err_t)result;
169 }
170 
sc_pm_set_cpu_resume_addr(sc_ipc_t ipc,sc_rsrc_t resource,sc_faddr_t address)171 sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource,
172 				   sc_faddr_t address)
173 {
174 	sc_rpc_msg_t msg;
175 	uint8_t result;
176 
177 	RPC_VER(&msg) = SC_RPC_VERSION;
178 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
179 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME_ADDR;
180 	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
181 	RPC_U32(&msg, 4U) = (uint32_t)address;
182 	RPC_U16(&msg, 8U) = (uint16_t)resource;
183 	RPC_SIZE(&msg) = 4U;
184 
185 	sc_call_rpc(ipc, &msg, SC_FALSE);
186 
187 	result = RPC_R8(&msg);
188 	return (sc_err_t)result;
189 }
190 
sc_pm_set_cpu_resume(sc_ipc_t ipc,sc_rsrc_t resource,sc_bool_t isPrimary,sc_faddr_t address)191 sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource,
192 			      sc_bool_t isPrimary, sc_faddr_t address)
193 {
194 	sc_rpc_msg_t msg;
195 	uint8_t result;
196 
197 	RPC_VER(&msg) = SC_RPC_VERSION;
198 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
199 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME;
200 	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
201 	RPC_U32(&msg, 4U) = (uint32_t)address;
202 	RPC_U16(&msg, 8U) = (uint16_t)resource;
203 	RPC_U8(&msg, 10U) = (uint8_t)isPrimary;
204 	RPC_SIZE(&msg) = 4U;
205 
206 	sc_call_rpc(ipc, &msg, SC_FALSE);
207 
208 	result = RPC_R8(&msg);
209 	return (sc_err_t)result;
210 }
211 
sc_pm_req_sys_if_power_mode(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_sys_if_t sys_if,sc_pm_power_mode_t hpm,sc_pm_power_mode_t lpm)212 sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
213 				     sc_pm_sys_if_t sys_if,
214 				     sc_pm_power_mode_t hpm,
215 				     sc_pm_power_mode_t lpm)
216 {
217 	sc_rpc_msg_t msg;
218 	uint8_t result;
219 
220 	RPC_VER(&msg) = SC_RPC_VERSION;
221 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
222 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_SYS_IF_POWER_MODE;
223 	RPC_U16(&msg, 0U) = (uint16_t)resource;
224 	RPC_U8(&msg, 2U) = (uint8_t)sys_if;
225 	RPC_U8(&msg, 3U) = (uint8_t)hpm;
226 	RPC_U8(&msg, 4U) = (uint8_t)lpm;
227 	RPC_SIZE(&msg) = 3U;
228 
229 	sc_call_rpc(ipc, &msg, SC_FALSE);
230 
231 	result = RPC_R8(&msg);
232 	return (sc_err_t)result;
233 }
234 
sc_pm_set_clock_rate(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_clk_t clk,sc_pm_clock_rate_t * rate)235 sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
236 			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
237 {
238 	sc_rpc_msg_t msg;
239 	uint8_t result;
240 
241 	RPC_VER(&msg) = SC_RPC_VERSION;
242 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
243 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_RATE;
244 	RPC_U32(&msg, 0U) = *(uint32_t *)rate;
245 	RPC_U16(&msg, 4U) = (uint16_t)resource;
246 	RPC_U8(&msg, 6U) = (uint8_t)clk;
247 	RPC_SIZE(&msg) = 3U;
248 
249 	sc_call_rpc(ipc, &msg, SC_FALSE);
250 
251 	*rate = RPC_U32(&msg, 0U);
252 	result = RPC_R8(&msg);
253 	return (sc_err_t)result;
254 }
255 
sc_pm_get_clock_rate(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_clk_t clk,sc_pm_clock_rate_t * rate)256 sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
257 			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
258 {
259 	sc_rpc_msg_t msg;
260 	uint8_t result;
261 
262 	RPC_VER(&msg) = SC_RPC_VERSION;
263 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
264 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_RATE;
265 	RPC_U16(&msg, 0U) = (uint16_t)resource;
266 	RPC_U8(&msg, 2U) = (uint8_t)clk;
267 	RPC_SIZE(&msg) = 2U;
268 
269 	sc_call_rpc(ipc, &msg, SC_FALSE);
270 
271 	if (rate != NULL) {
272 		*rate = RPC_U32(&msg, 0U);
273 	}
274 
275 	result = RPC_R8(&msg);
276 	return (sc_err_t)result;
277 }
278 
sc_pm_clock_enable(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_clk_t clk,sc_bool_t enable,sc_bool_t autog)279 sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource,
280 			    sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog)
281 {
282 	sc_rpc_msg_t msg;
283 	uint8_t result;
284 
285 	RPC_VER(&msg) = SC_RPC_VERSION;
286 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
287 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CLOCK_ENABLE;
288 	RPC_U16(&msg, 0U) = (uint16_t)resource;
289 	RPC_U8(&msg, 2U) = (uint8_t)clk;
290 	RPC_U8(&msg, 3U) = (uint8_t)enable;
291 	RPC_U8(&msg, 4U) = (uint8_t)autog;
292 	RPC_SIZE(&msg) = 3U;
293 
294 	sc_call_rpc(ipc, &msg, SC_FALSE);
295 
296 	result = RPC_R8(&msg);
297 	return (sc_err_t)result;
298 }
299 
sc_pm_set_clock_parent(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_clk_t clk,sc_pm_clk_parent_t parent)300 sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
301 				sc_pm_clk_t clk, sc_pm_clk_parent_t parent)
302 {
303 	sc_rpc_msg_t msg;
304 	uint8_t result;
305 
306 	RPC_VER(&msg) = SC_RPC_VERSION;
307 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
308 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_PARENT;
309 	RPC_U16(&msg, 0U) = (uint16_t)resource;
310 	RPC_U8(&msg, 2U) = (uint8_t)clk;
311 	RPC_U8(&msg, 3U) = (uint8_t)parent;
312 	RPC_SIZE(&msg) = 2U;
313 
314 	sc_call_rpc(ipc, &msg, SC_FALSE);
315 
316 	result = RPC_R8(&msg);
317 	return (sc_err_t)result;
318 }
319 
sc_pm_get_clock_parent(sc_ipc_t ipc,sc_rsrc_t resource,sc_pm_clk_t clk,sc_pm_clk_parent_t * parent)320 sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
321 				sc_pm_clk_t clk, sc_pm_clk_parent_t *parent)
322 {
323 	sc_rpc_msg_t msg;
324 	uint8_t result;
325 
326 	RPC_VER(&msg) = SC_RPC_VERSION;
327 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
328 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_PARENT;
329 	RPC_U16(&msg, 0U) = (uint16_t)resource;
330 	RPC_U8(&msg, 2U) = (uint8_t)clk;
331 	RPC_SIZE(&msg) = 2U;
332 
333 	sc_call_rpc(ipc, &msg, SC_FALSE);
334 
335 	result = RPC_R8(&msg);
336 	if (parent != NULL) {
337 		*parent = RPC_U8(&msg, 0U);
338 	}
339 
340 	return (sc_err_t)result;
341 }
342 
sc_pm_reset(sc_ipc_t ipc,sc_pm_reset_type_t type)343 sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type)
344 {
345 	sc_rpc_msg_t msg;
346 	uint8_t result;
347 
348 	RPC_VER(&msg) = SC_RPC_VERSION;
349 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
350 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET;
351 	RPC_U8(&msg, 0U) = (uint8_t)type;
352 	RPC_SIZE(&msg) = 2U;
353 
354 	sc_call_rpc(ipc, &msg, SC_FALSE);
355 
356 	result = RPC_R8(&msg);
357 	return (sc_err_t)result;
358 }
359 
sc_pm_reset_reason(sc_ipc_t ipc,sc_pm_reset_reason_t * reason)360 sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason)
361 {
362 	sc_rpc_msg_t msg;
363 	uint8_t result;
364 
365 	RPC_VER(&msg) = SC_RPC_VERSION;
366 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
367 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET_REASON;
368 	RPC_SIZE(&msg) = 1U;
369 
370 	sc_call_rpc(ipc, &msg, SC_FALSE);
371 
372 	result = RPC_R8(&msg);
373 	if (reason != NULL) {
374 		*reason = RPC_U8(&msg, 0U);
375 	}
376 
377 	return (sc_err_t)result;
378 }
379 
sc_pm_boot(sc_ipc_t ipc,sc_rm_pt_t pt,sc_rsrc_t resource_cpu,sc_faddr_t boot_addr,sc_rsrc_t resource_mu,sc_rsrc_t resource_dev)380 sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt,
381 		    sc_rsrc_t resource_cpu, sc_faddr_t boot_addr,
382 		    sc_rsrc_t resource_mu, sc_rsrc_t resource_dev)
383 {
384 	sc_rpc_msg_t msg;
385 	uint8_t result;
386 
387 	RPC_VER(&msg) = SC_RPC_VERSION;
388 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
389 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_BOOT;
390 	RPC_U32(&msg, 0U) = (uint32_t)(boot_addr >> 32U);
391 	RPC_U32(&msg, 4U) = (uint32_t)boot_addr;
392 	RPC_U16(&msg, 8U) = (uint16_t)resource_cpu;
393 	RPC_U16(&msg, 10U) = (uint16_t)resource_mu;
394 	RPC_U16(&msg, 12U) = (uint16_t)resource_dev;
395 	RPC_U8(&msg, 14U) = (uint8_t)pt;
396 	RPC_SIZE(&msg) = 5U;
397 
398 	sc_call_rpc(ipc, &msg, SC_FALSE);
399 
400 	result = RPC_R8(&msg);
401 	return (sc_err_t)result;
402 }
403 
sc_pm_reboot(sc_ipc_t ipc,sc_pm_reset_type_t type)404 void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type)
405 {
406 	sc_rpc_msg_t msg;
407 
408 	RPC_VER(&msg) = SC_RPC_VERSION;
409 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
410 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT;
411 	RPC_U8(&msg, 0U) = (uint8_t)type;
412 	RPC_SIZE(&msg) = 2U;
413 
414 	sc_call_rpc(ipc, &msg, SC_TRUE);
415 
416 	return;
417 }
418 
sc_pm_reboot_partition(sc_ipc_t ipc,sc_rm_pt_t pt,sc_pm_reset_type_t type)419 sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt,
420 				sc_pm_reset_type_t type)
421 {
422 	sc_rpc_msg_t msg;
423 	uint8_t result;
424 
425 	RPC_VER(&msg) = SC_RPC_VERSION;
426 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
427 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT_PARTITION;
428 	RPC_U8(&msg, 0U) = (uint8_t)pt;
429 	RPC_U8(&msg, 1U) = (uint8_t)type;
430 	RPC_SIZE(&msg) = 2U;
431 
432 	sc_call_rpc(ipc, &msg, SC_FALSE);
433 
434 	result = RPC_R8(&msg);
435 	return (sc_err_t)result;
436 }
437 
sc_pm_cpu_start(sc_ipc_t ipc,sc_rsrc_t resource,sc_bool_t enable,sc_faddr_t address)438 sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable,
439 			 sc_faddr_t address)
440 {
441 	sc_rpc_msg_t msg;
442 	uint8_t result;
443 
444 	RPC_VER(&msg) = SC_RPC_VERSION;
445 	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
446 	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CPU_START;
447 	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
448 	RPC_U32(&msg, 4U) = (uint32_t)address;
449 	RPC_U16(&msg, 8U) = (uint16_t)resource;
450 	RPC_U8(&msg, 10U) = (uint8_t)enable;
451 	RPC_SIZE(&msg) = 4U;
452 
453 	sc_call_rpc(ipc, &msg, SC_FALSE);
454 
455 	result = RPC_R8(&msg);
456 	return (sc_err_t)result;
457 }
458 
459 /**@}*/
460