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