1 /* 2 * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. 3 * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 /* 9 * Versal system level PM-API functions and communication with PMC via 10 * IPI interrupts 11 */ 12 13 #include <drivers/arm/gic_common.h> 14 #include <lib/mmio.h> 15 #include <lib/utils.h> 16 #include <plat/common/platform.h> 17 #include <platform_def.h> 18 #include <pm_api_sys.h> 19 #include <pm_client.h> 20 #include <pm_common.h> 21 #include <pm_defs.h> 22 #include <pm_ipi.h> 23 #include "pm_svc_main.h" 24 25 #define NUM_GICD_ISENABLER ((IRQ_MAX >> 5U) + 1U) 26 27 /* default shutdown/reboot scope is system(2) */ 28 static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; 29 30 /** 31 * pm_get_shutdown_scope() - Get the currently set shutdown scope. 32 * 33 * Return: Shutdown scope value. 34 * 35 */ 36 uint32_t pm_get_shutdown_scope(void) 37 { 38 return pm_shutdown_scope; 39 } 40 41 /* PM API functions */ 42 43 /** 44 * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as 45 * wake sources in the XilPM. 46 * @node_id: Node id of processor. 47 * 48 */ 49 void pm_client_set_wakeup_sources(uint32_t node_id) 50 { 51 uint32_t reg_num, device_id; 52 uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX] = {0U}; 53 uint32_t isenabler1 = PLAT_ARM_GICD_BASE + GICD_ISENABLER + 4U; 54 55 zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set)); 56 57 for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) { 58 uint32_t base_irq = reg_num << ISENABLER_SHIFT; 59 uint32_t reg = mmio_read_32((uint64_t)(isenabler1 + (reg_num << 2))); 60 61 if (reg == 0U) { 62 continue; 63 } 64 65 while (reg != 0U) { 66 enum pm_device_node_idx node_idx; 67 uint32_t idx, irq, lowest_set = reg & (-reg); 68 enum pm_ret_status ret; 69 70 idx = (uint32_t)__builtin_ctz(lowest_set); 71 irq = base_irq + idx; 72 73 if (irq > IRQ_MAX) { 74 break; 75 } 76 77 node_idx = irq_to_pm_node_idx(irq); 78 reg &= ~lowest_set; 79 80 if (node_idx > XPM_NODEIDX_DEV_MIN) { 81 if (pm_wakeup_nodes_set[node_idx] == 0U) { 82 /* Get device ID from node index */ 83 device_id = PERIPH_DEVID((uint32_t)node_idx); 84 ret = pm_set_wakeup_source(node_id, 85 device_id, 1U, 86 SECURE_FLAG); 87 pm_wakeup_nodes_set[node_idx] = (ret == PM_RET_SUCCESS) ? 88 1U : 0U; 89 } 90 } 91 } 92 } 93 } 94 95 /** 96 * pm_handle_eemi_call() - PM call for processor to send eemi payload. 97 * @flag: 0 - Call from secure source. 98 * 1 - Call from non-secure source. 99 * @x0: Arguments received per SMC64 standard. 100 * @x1: Arguments received per SMC64 standard. 101 * @x2: Arguments received per SMC64 standard. 102 * @x3: Arguments received per SMC64 standard. 103 * @x4: Arguments received per SMC64 standard. 104 * @x5: Arguments received per SMC64 standard. 105 * @result: Payload received from firmware. 106 * 107 * Return: PM_RET_SUCCESS on success or error code. 108 * 109 */ 110 enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1, 111 uint32_t x2, uint32_t x3, uint32_t x4, 112 uint32_t x5, uint32_t *result) 113 { 114 uint32_t payload[PAYLOAD_ARG_CNT] = {0}; 115 uint32_t module_id; 116 117 module_id = (x0 & MODULE_ID_MASK) >> 8U; 118 119 //default module id is for LIBPM 120 if (module_id == 0U) { 121 module_id = LIBPM_MODULE_ID; 122 } 123 124 PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5); 125 return pm_ipi_send_sync(primary_proc, payload, result, RET_PAYLOAD_ARG_CNT); 126 } 127 128 /** 129 * pm_self_suspend() - PM call for processor to suspend itself 130 * @nid: Node id of the processor or subsystem. 131 * @latency: Requested maximum wakeup latency (not supported). 132 * @state: Requested state. 133 * @address: Resume address. 134 * @flag: 0 - Call from secure source. 135 * 1 - Call from non-secure source. 136 * 137 * This is a blocking call, it will return only once PMU has responded. 138 * On a wakeup, resume address will be automatically set by PMU. 139 * 140 * Return: Returns status, either success or error+reason. 141 * 142 */ 143 enum pm_ret_status pm_self_suspend(uint32_t nid, 144 uint32_t latency, 145 uint32_t state, 146 uintptr_t address, uint32_t flag) 147 { 148 uint32_t payload[PAYLOAD_ARG_CNT]; 149 uint32_t cpuid = plat_my_core_pos(); 150 const struct pm_proc *proc = pm_get_proc(cpuid); 151 enum pm_ret_status ret = PM_RET_ERROR_INTERNAL; 152 153 if (proc == NULL) { 154 WARN("Failed to get proc %d\n", cpuid); 155 goto exit_label; 156 } 157 158 /* 159 * Do client specific suspend operations 160 * (e.g. set powerdown request bit) 161 */ 162 pm_client_suspend(proc, state); 163 164 /* Send request to the PLM */ 165 PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND, 166 nid, latency, state, address, (address >> 32)); 167 ret = pm_ipi_send_sync(proc, payload, NULL, 0); 168 169 exit_label: 170 return ret; 171 } 172 173 /** 174 * pm_abort_suspend() - PM call to announce that a prior suspend request 175 * is to be aborted. 176 * @reason: Reason for the abort. 177 * @flag: 0 - Call from secure source. 178 * 1 - Call from non-secure source. 179 * 180 * Calling PU expects the PMU to abort the initiated suspend procedure. 181 * This is a non-blocking call without any acknowledge. 182 * 183 * Return: Returns status, either success or error+reason. 184 * 185 */ 186 enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag) 187 { 188 uint32_t payload[PAYLOAD_ARG_CNT]; 189 190 /* 191 * Do client specific abort suspend operations 192 * (e.g. enable interrupts and clear powerdown request bit) 193 */ 194 pm_client_abort_suspend(); 195 196 /* Send request to the PLM */ 197 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND, 198 reason, primary_proc->node_id); 199 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 200 } 201 202 /** 203 * pm_req_suspend() - PM call to request for another PU or subsystem to 204 * be suspended gracefully. 205 * @target: Node id of the targeted PU or subsystem. 206 * @ack: Flag to specify whether acknowledge is requested. 207 * @latency: Requested wakeup latency (not supported) 208 * @state: Requested state (not supported). 209 * @flag: 0 - Call from secure source. 210 * 1 - Call from non-secure source. 211 * 212 * Return: Returns status, either success or error+reason. 213 * 214 */ 215 enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, 216 uint32_t latency, uint32_t state, 217 uint32_t flag) 218 { 219 uint32_t payload[PAYLOAD_ARG_CNT]; 220 enum pm_ret_status ret = PM_RET_SUCCESS; 221 222 /* Send request to the PMU */ 223 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target, 224 latency, state); 225 if (ack == (uint32_t)IPI_BLOCKING) { 226 ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0); 227 } else { 228 ret = pm_ipi_send(primary_proc, payload); 229 } 230 231 return ret; 232 } 233 234 /** 235 * pm_req_wakeup() - PM call for processor to wake up selected processor 236 * or subsystem. 237 * @target: Device ID of the processor or subsystem to wake up. 238 * @set_address: Resume address presence indicator. 239 * 1 - resume address specified, 0 - otherwise. 240 * @address: Resume address. 241 * @ack: Flag to specify whether acknowledge requested. 242 * @flag: 0 - Call from secure source. 243 * 1 - Call from non-secure source. 244 * 245 * This API function is either used to power up another APU core for SMP 246 * (by PSCI) or to power up an entirely different PU or subsystem, such 247 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be 248 * automatically set by PMC. 249 * 250 * Return: Returns status, either success or error+reason. 251 * 252 */ 253 enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, 254 uintptr_t address, uint8_t ack, uint32_t flag) 255 { 256 uint32_t payload[PAYLOAD_ARG_CNT]; 257 258 /* Send request to the PMC to perform the wake of the PU */ 259 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target, 260 set_address, address, ack); 261 262 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 263 } 264 265 /** 266 * pm_get_callbackdata() - Read from IPI response buffer. 267 * @data: array of PAYLOAD_ARG_CNT elements. 268 * @count: Number of values to return. 269 * @flag: 0 - Call from secure source. 270 * 1 - Call from non-secure source. 271 * @ack: 0 - Do not ack IPI after reading payload. 272 * 1 - Ack IPI after reading payload. 273 * 274 * Read value from ipi buffer response buffer. 275 * Return: Returns status, either success or error. 276 * 277 */ 278 enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack) 279 { 280 enum pm_ret_status ret = PM_RET_SUCCESS; 281 282 /* 283 * Typecasting to void to intentionally retain the variable and avoid 284 * MISRA violation for unused parameters. This may be used in the 285 * future if callbacks to a secure target are required. 286 */ 287 (void)flag; 288 289 /* Return if interrupt is not from PMU */ 290 if (pm_ipi_irq_status(primary_proc) != 0U) { 291 292 ret = pm_ipi_buff_read_callb(data, count); 293 294 if (ack != 0U) { 295 pm_ipi_irq_clear(primary_proc); 296 } 297 } 298 299 return ret; 300 } 301 302 /** 303 * pm_force_powerdown() - PM call to request for another PU or subsystem to 304 * be powered down forcefully. 305 * @target: Device ID of the PU node to be forced powered down. 306 * @ack: Flag to specify whether acknowledge is requested 307 * @flag: 0 - Call from secure source 308 * 1 - Call from non-secure source 309 * 310 * Return: Returns status, either success or error+reason. 311 * 312 */ 313 enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack, 314 uint32_t flag) 315 { 316 uint32_t payload[PAYLOAD_ARG_CNT]; 317 enum pm_ret_status ret = PM_RET_SUCCESS; 318 319 /* Send request to the PMC */ 320 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN, 321 target, ack); 322 323 if (ack == (uint32_t)IPI_BLOCKING) { 324 ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0); 325 } else { 326 ret = pm_ipi_send(primary_proc, payload); 327 } 328 329 return ret; 330 } 331 332 /** 333 * pm_system_shutdown() - PM call to request a system shutdown or restart. 334 * @type: Shutdown or restart? 0=shutdown, 1=restart, 2=setscope. 335 * @subtype: Scope: 0=APU-subsystem, 1=PS, 2=system. 336 * @flag: 0 - Call from secure source. 337 * 1 - Call from non-secure source. 338 * 339 * Return: Returns status, either success or error+reason. 340 * 341 */ 342 enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, 343 uint32_t flag) 344 { 345 uint32_t payload[PAYLOAD_ARG_CNT]; 346 enum pm_ret_status ret = PM_RET_SUCCESS; 347 348 if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) { 349 /* Setting scope for subsequent PSCI reboot or shutdown */ 350 pm_shutdown_scope = subtype; 351 goto exit_label; 352 } 353 354 /* Send request to the PMC */ 355 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN, 356 type, subtype); 357 358 ret = pm_ipi_send_non_blocking(primary_proc, payload); 359 360 exit_label: 361 return ret; 362 } 363 364 /** 365 * pm_set_wakeup_source() - PM call to specify the wakeup source while 366 * suspended. 367 * @target: Device id of the targeted PU or subsystem 368 * @wkup_device: Device id of the wakeup peripheral 369 * @enable: Enable or disable the specified peripheral as wake source 370 * @flag: 0 - Call from secure source 371 * 1 - Call from non-secure source 372 * 373 * Return: Returns status, either success or error+reason. 374 * 375 */ 376 enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, 377 uint8_t enable, uint32_t flag) 378 { 379 uint32_t payload[PAYLOAD_ARG_CNT]; 380 381 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE, 382 target, wkup_device, enable); 383 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 384 } 385 386 /** 387 * eemi_feature_check() - Returns the supported API version if supported. 388 * @api_id: API ID to check. 389 * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of 390 * words Returned supported API version 391 * 392 * Return: Returns status, either success or error+reason. 393 */ 394 enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload) 395 { 396 enum pm_ret_status ret; 397 398 /* Return version of API which are implemented in TF-A only */ 399 switch (api_id) { 400 case PM_GET_CALLBACK_DATA: 401 case PM_GET_TRUSTZONE_VERSION: 402 ret_payload[0] = PM_API_VERSION_2; 403 ret = PM_RET_SUCCESS; 404 break; 405 case TF_A_PM_REGISTER_SGI: 406 case TF_A_FEATURE_CHECK: 407 ret_payload[0] = PM_API_BASE_VERSION; 408 ret = PM_RET_SUCCESS; 409 break; 410 default: 411 ret = PM_RET_ERROR_NO_FEATURE; 412 } 413 414 return ret; 415 } 416 417 /** 418 * pm_feature_check() - Returns the supported API version if supported. 419 * @api_id: API ID to check. 420 * @flag: 0 - Call from secure source. 421 * 1 - Call from non-secure source. 422 * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of 423 * words Returned supported API version and bitmasks 424 * for IOCTL and QUERY ID 425 * 426 * Return: Returns status, either success or error+reason. 427 * 428 */ 429 enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload, 430 uint32_t flag) 431 { 432 uint32_t payload[PAYLOAD_ARG_CNT]; 433 uint32_t module_id; 434 enum pm_ret_status ret; 435 436 /* Return version of API which are implemented in TF-A only */ 437 switch (api_id) { 438 case PM_GET_CALLBACK_DATA: 439 case PM_GET_TRUSTZONE_VERSION: 440 ret_payload[0] = PM_API_VERSION_2; 441 ret = PM_RET_SUCCESS; 442 goto exit_label; 443 case TF_A_PM_REGISTER_SGI: 444 ret_payload[0] = PM_API_BASE_VERSION; 445 ret = PM_RET_SUCCESS; 446 goto exit_label; 447 default: 448 break; 449 } 450 451 module_id = (api_id & MODULE_ID_MASK) >> 8U; 452 453 /* 454 * feature check should be done only for LIBPM module 455 * If module_id is 0, then we consider it LIBPM module as default id 456 */ 457 if ((module_id > 0U) && (module_id != LIBPM_MODULE_ID)) { 458 ret = PM_RET_SUCCESS; 459 goto exit_label; 460 } 461 462 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, 463 PM_FEATURE_CHECK, api_id); 464 ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT); 465 466 exit_label: 467 return ret; 468 469 } 470 471 /** 472 * pm_load_pdi() - Load the PDI. This function provides support to load 473 * PDI from linux. 474 * 475 * @src: Source device of pdi(DDR, OCM, SD etc). 476 * @address_low: lower 32-bit Linear memory space address. 477 * @address_high: higher 32-bit Linear memory space address. 478 * @flag: 0 - Call from secure source. 479 * 1 - Call from non-secure source. 480 * 481 * Return: Returns status, either success or error+reason. 482 * 483 */ 484 enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, 485 uint32_t address_high, uint32_t flag) 486 { 487 uint32_t payload[PAYLOAD_ARG_CNT]; 488 489 /* Send request to the PMU */ 490 PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src, 491 address_high, address_low); 492 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 493 } 494 495 /** 496 * pm_register_notifier() - PM call to register a subsystem to be notified 497 * about the device event. 498 * @device_id: Device ID for the Node to which the event is related. 499 * @event: Event in question. 500 * @wake: Wake subsystem upon capturing the event if value 1. 501 * @enable: Enable the registration for value 1, disable for value 0. 502 * @flag: 0 - Call from secure source. 503 * 1 - Call from non-secure source. 504 * 505 * Return: Returns status, either success or error+reason. 506 * 507 */ 508 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, 509 uint32_t wake, uint32_t enable, 510 uint32_t flag) 511 { 512 uint32_t payload[PAYLOAD_ARG_CNT]; 513 514 /* Send request to the PMC */ 515 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER, 516 device_id, event, wake, enable); 517 518 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 519 } 520 521 /** 522 * pm_get_chipid() - Read silicon ID registers. 523 * @value: Buffer for two 32bit words. 524 * 525 * Return: Returns status, either success or error+reason and, 526 * optionally, @value. 527 */ 528 enum pm_ret_status pm_get_chipid(uint32_t *value) 529 { 530 uint32_t payload[PAYLOAD_ARG_CNT]; 531 532 PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, SECURE_FLAG, PM_GET_CHIPID); 533 534 return pm_ipi_send_sync(primary_proc, payload, value, 2); 535 } 536