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 break; 413 } 414 415 return ret; 416 } 417 418 /** 419 * pm_feature_check() - Returns the supported API version if supported. 420 * @api_id: API ID to check. 421 * @flag: 0 - Call from secure source. 422 * 1 - Call from non-secure source. 423 * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of 424 * words Returned supported API version and bitmasks 425 * for IOCTL and QUERY ID 426 * 427 * Return: Returns status, either success or error+reason. 428 * 429 */ 430 enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload, 431 uint32_t flag) 432 { 433 uint32_t payload[PAYLOAD_ARG_CNT]; 434 uint32_t module_id; 435 enum pm_ret_status ret; 436 437 /* Return version of API which are implemented in TF-A only */ 438 switch (api_id) { 439 case PM_GET_CALLBACK_DATA: 440 case PM_GET_TRUSTZONE_VERSION: 441 ret_payload[0] = PM_API_VERSION_2; 442 ret = PM_RET_SUCCESS; 443 break; 444 case TF_A_PM_REGISTER_SGI: 445 ret_payload[0] = PM_API_BASE_VERSION; 446 ret = PM_RET_SUCCESS; 447 break; 448 default: 449 module_id = (api_id & MODULE_ID_MASK) >> 8U; 450 451 /* 452 * feature check should be done only for LIBPM module 453 * If module_id is 0, then we consider it LIBPM module as default id 454 */ 455 if ((module_id > 0U) && (module_id != LIBPM_MODULE_ID)) { 456 ret = PM_RET_SUCCESS; 457 break; 458 } 459 460 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, 461 PM_FEATURE_CHECK, api_id); 462 ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT); 463 464 break; 465 } 466 467 return ret; 468 } 469 470 /** 471 * pm_load_pdi() - Load the PDI. This function provides support to load 472 * PDI from linux. 473 * 474 * @src: Source device of pdi(DDR, OCM, SD etc). 475 * @address_low: lower 32-bit Linear memory space address. 476 * @address_high: higher 32-bit Linear memory space address. 477 * @flag: 0 - Call from secure source. 478 * 1 - Call from non-secure source. 479 * 480 * Return: Returns status, either success or error+reason. 481 * 482 */ 483 enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, 484 uint32_t address_high, uint32_t flag) 485 { 486 uint32_t payload[PAYLOAD_ARG_CNT]; 487 488 /* Send request to the PMU */ 489 PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src, 490 address_high, address_low); 491 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 492 } 493 494 /** 495 * pm_register_notifier() - PM call to register a subsystem to be notified 496 * about the device event. 497 * @device_id: Device ID for the Node to which the event is related. 498 * @event: Event in question. 499 * @wake: Wake subsystem upon capturing the event if value 1. 500 * @enable: Enable the registration for value 1, disable for value 0. 501 * @flag: 0 - Call from secure source. 502 * 1 - Call from non-secure source. 503 * 504 * Return: Returns status, either success or error+reason. 505 * 506 */ 507 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, 508 uint32_t wake, uint32_t enable, 509 uint32_t flag) 510 { 511 uint32_t payload[PAYLOAD_ARG_CNT]; 512 513 /* Send request to the PMC */ 514 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER, 515 device_id, event, wake, enable); 516 517 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 518 } 519 520 /** 521 * pm_get_chipid() - Read silicon ID registers. 522 * @value: Buffer for two 32bit words. 523 * 524 * Return: Returns status, either success or error+reason and, 525 * optionally, @value. 526 */ 527 enum pm_ret_status pm_get_chipid(uint32_t *value) 528 { 529 uint32_t payload[PAYLOAD_ARG_CNT]; 530 531 PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, SECURE_FLAG, PM_GET_CHIPID); 532 533 return pm_ipi_send_sync(primary_proc, payload, value, 2); 534 } 535