1 /* 2 * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. 3 * Copyright (c) 2022-2024, 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, uint64_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, (uint32_t *)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 proc->node_id, latency, state, address, 167 (address >> 32)); 168 ret = pm_ipi_send_sync(proc, payload, NULL, 0); 169 170 exit_label: 171 return ret; 172 } 173 174 /** 175 * pm_abort_suspend() - PM call to announce that a prior suspend request 176 * is to be aborted. 177 * @reason: Reason for the abort. 178 * @flag: 0 - Call from secure source. 179 * 1 - Call from non-secure source. 180 * 181 * Calling PU expects the PMU to abort the initiated suspend procedure. 182 * This is a non-blocking call without any acknowledge. 183 * 184 * Return: Returns status, either success or error+reason. 185 * 186 */ 187 enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag) 188 { 189 uint32_t payload[PAYLOAD_ARG_CNT]; 190 191 /* 192 * Do client specific abort suspend operations 193 * (e.g. enable interrupts and clear powerdown request bit) 194 */ 195 pm_client_abort_suspend(); 196 197 /* Send request to the PLM */ 198 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND, 199 reason, primary_proc->node_id); 200 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 201 } 202 203 /** 204 * pm_req_suspend() - PM call to request for another PU or subsystem to 205 * be suspended gracefully. 206 * @target: Node id of the targeted PU or subsystem. 207 * @ack: Flag to specify whether acknowledge is requested. 208 * @latency: Requested wakeup latency (not supported) 209 * @state: Requested state (not supported). 210 * @flag: 0 - Call from secure source. 211 * 1 - Call from non-secure source. 212 * 213 * Return: Returns status, either success or error+reason. 214 * 215 */ 216 enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, 217 uint32_t latency, uint32_t state, 218 uint32_t flag) 219 { 220 uint32_t payload[PAYLOAD_ARG_CNT]; 221 enum pm_ret_status ret = PM_RET_SUCCESS; 222 223 /* Send request to the PMU */ 224 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target, 225 latency, state); 226 if (ack == (uint32_t)IPI_BLOCKING) { 227 ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0); 228 } else { 229 ret = pm_ipi_send(primary_proc, payload); 230 } 231 232 return ret; 233 } 234 235 /** 236 * pm_req_wakeup() - PM call for processor to wake up selected processor 237 * or subsystem. 238 * @target: Device ID of the processor or subsystem to wake up. 239 * @set_address: Resume address presence indicator. 240 * 1 - resume address specified, 0 - otherwise. 241 * @address: Resume address. 242 * @ack: Flag to specify whether acknowledge requested. 243 * @flag: 0 - Call from secure source. 244 * 1 - Call from non-secure source. 245 * 246 * This API function is either used to power up another APU core for SMP 247 * (by PSCI) or to power up an entirely different PU or subsystem, such 248 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be 249 * automatically set by PMC. 250 * 251 * Return: Returns status, either success or error+reason. 252 * 253 */ 254 enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, 255 uintptr_t address, uint8_t ack, uint32_t flag) 256 { 257 uint32_t payload[PAYLOAD_ARG_CNT]; 258 259 /* Send request to the PMC to perform the wake of the PU */ 260 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target, 261 set_address, address, ack); 262 263 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 264 } 265 266 /** 267 * pm_get_callbackdata() - Read from IPI response buffer. 268 * @data: array of PAYLOAD_ARG_CNT elements. 269 * @count: Number of values to return. 270 * @flag: 0 - Call from secure source. 271 * 1 - Call from non-secure source. 272 * @ack: 0 - Do not ack IPI after reading payload. 273 * 1 - Ack IPI after reading payload. 274 * 275 * Read value from ipi buffer response buffer. 276 * Return: Returns status, either success or error. 277 * 278 */ 279 enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack) 280 { 281 enum pm_ret_status ret = PM_RET_SUCCESS; 282 283 /* Return if interrupt is not from PMU */ 284 if (pm_ipi_irq_status(primary_proc) != 0U) { 285 286 ret = pm_ipi_buff_read_callb(data, count); 287 288 if (ack != 0U) { 289 pm_ipi_irq_clear(primary_proc); 290 } 291 } 292 293 return ret; 294 } 295 296 /** 297 * pm_force_powerdown() - PM call to request for another PU or subsystem to 298 * be powered down forcefully. 299 * @target: Device ID of the PU node to be forced powered down. 300 * @ack: Flag to specify whether acknowledge is requested 301 * @flag: 0 - Call from secure source 302 * 1 - Call from non-secure source 303 * 304 * Return: Returns status, either success or error+reason. 305 * 306 */ 307 enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack, 308 uint32_t flag) 309 { 310 uint32_t payload[PAYLOAD_ARG_CNT]; 311 enum pm_ret_status ret = PM_RET_SUCCESS; 312 313 /* Send request to the PMC */ 314 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN, 315 target, ack); 316 317 if (ack == (uint32_t)IPI_BLOCKING) { 318 ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0); 319 } else { 320 ret = pm_ipi_send(primary_proc, payload); 321 } 322 323 return ret; 324 } 325 326 /** 327 * pm_system_shutdown() - PM call to request a system shutdown or restart. 328 * @type: Shutdown or restart? 0=shutdown, 1=restart, 2=setscope. 329 * @subtype: Scope: 0=APU-subsystem, 1=PS, 2=system. 330 * @flag: 0 - Call from secure source. 331 * 1 - Call from non-secure source. 332 * 333 * Return: Returns status, either success or error+reason. 334 * 335 */ 336 enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, 337 uint32_t flag) 338 { 339 uint32_t payload[PAYLOAD_ARG_CNT]; 340 enum pm_ret_status ret = PM_RET_SUCCESS; 341 342 if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) { 343 /* Setting scope for subsequent PSCI reboot or shutdown */ 344 pm_shutdown_scope = subtype; 345 goto exit_label; 346 } 347 348 /* Send request to the PMC */ 349 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN, 350 type, subtype); 351 352 ret = pm_ipi_send_non_blocking(primary_proc, payload); 353 354 exit_label: 355 return ret; 356 } 357 358 /** 359 * pm_set_wakeup_source() - PM call to specify the wakeup source while 360 * suspended. 361 * @target: Device id of the targeted PU or subsystem 362 * @wkup_device: Device id of the wakeup peripheral 363 * @enable: Enable or disable the specified peripheral as wake source 364 * @flag: 0 - Call from secure source 365 * 1 - Call from non-secure source 366 * 367 * Return: Returns status, either success or error+reason. 368 * 369 */ 370 enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, 371 uint8_t enable, uint32_t flag) 372 { 373 uint32_t payload[PAYLOAD_ARG_CNT]; 374 375 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE, 376 target, wkup_device, enable); 377 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 378 } 379 380 /** 381 * eemi_feature_check() - Returns the supported API version if supported. 382 * @api_id: API ID to check. 383 * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of 384 * words Returned supported API version 385 * 386 * Return: Returns status, either success or error+reason. 387 */ 388 enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload) 389 { 390 enum pm_ret_status ret; 391 392 /* Return version of API which are implemented in TF-A only */ 393 switch (api_id) { 394 case PM_GET_CALLBACK_DATA: 395 case PM_GET_TRUSTZONE_VERSION: 396 ret_payload[0] = PM_API_VERSION_2; 397 ret = PM_RET_SUCCESS; 398 break; 399 case TF_A_PM_REGISTER_SGI: 400 case TF_A_FEATURE_CHECK: 401 ret_payload[0] = PM_API_BASE_VERSION; 402 ret = PM_RET_SUCCESS; 403 break; 404 default: 405 ret = PM_RET_ERROR_NO_FEATURE; 406 } 407 408 return ret; 409 } 410 411 /** 412 * pm_feature_check() - Returns the supported API version if supported. 413 * @api_id: API ID to check. 414 * @flag: 0 - Call from secure source. 415 * 1 - Call from non-secure source. 416 * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of 417 * words Returned supported API version and bitmasks 418 * for IOCTL and QUERY ID 419 * 420 * Return: Returns status, either success or error+reason. 421 * 422 */ 423 enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload, 424 uint32_t flag) 425 { 426 uint32_t payload[PAYLOAD_ARG_CNT]; 427 uint32_t module_id; 428 enum pm_ret_status ret; 429 430 /* Return version of API which are implemented in TF-A only */ 431 switch (api_id) { 432 case PM_GET_CALLBACK_DATA: 433 case PM_GET_TRUSTZONE_VERSION: 434 ret_payload[0] = PM_API_VERSION_2; 435 ret = PM_RET_SUCCESS; 436 goto exit_label; 437 case TF_A_PM_REGISTER_SGI: 438 ret_payload[0] = PM_API_BASE_VERSION; 439 ret = PM_RET_SUCCESS; 440 goto exit_label; 441 default: 442 break; 443 } 444 445 module_id = (api_id & MODULE_ID_MASK) >> 8U; 446 447 /* 448 * feature check should be done only for LIBPM module 449 * If module_id is 0, then we consider it LIBPM module as default id 450 */ 451 if ((module_id > 0U) && (module_id != LIBPM_MODULE_ID)) { 452 ret = PM_RET_SUCCESS; 453 goto exit_label; 454 } 455 456 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, 457 PM_FEATURE_CHECK, api_id); 458 ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT); 459 460 exit_label: 461 return ret; 462 463 } 464 465 /** 466 * pm_load_pdi() - Load the PDI. This function provides support to load 467 * PDI from linux. 468 * 469 * @src: Source device of pdi(DDR, OCM, SD etc). 470 * @address_low: lower 32-bit Linear memory space address. 471 * @address_high: higher 32-bit Linear memory space address. 472 * @flag: 0 - Call from secure source. 473 * 1 - Call from non-secure source. 474 * 475 * Return: Returns status, either success or error+reason. 476 * 477 */ 478 enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, 479 uint32_t address_high, uint32_t flag) 480 { 481 uint32_t payload[PAYLOAD_ARG_CNT]; 482 483 /* Send request to the PMU */ 484 PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src, 485 address_high, address_low); 486 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 487 } 488 489 /** 490 * pm_register_notifier() - PM call to register a subsystem to be notified 491 * about the device event. 492 * @device_id: Device ID for the Node to which the event is related. 493 * @event: Event in question. 494 * @wake: Wake subsystem upon capturing the event if value 1. 495 * @enable: Enable the registration for value 1, disable for value 0. 496 * @flag: 0 - Call from secure source. 497 * 1 - Call from non-secure source. 498 * 499 * Return: Returns status, either success or error+reason. 500 * 501 */ 502 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, 503 uint32_t wake, uint32_t enable, 504 uint32_t flag) 505 { 506 uint32_t payload[PAYLOAD_ARG_CNT]; 507 508 /* Send request to the PMC */ 509 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER, 510 device_id, event, wake, enable); 511 512 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 513 } 514 515 /** 516 * pm_get_chipid() - Read silicon ID registers. 517 * @value: Buffer for two 32bit words. 518 * 519 * Return: Returns status, either success or error+reason and, 520 * optionally, @value. 521 */ 522 enum pm_ret_status pm_get_chipid(uint32_t *value) 523 { 524 uint32_t payload[PAYLOAD_ARG_CNT]; 525 526 PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, SECURE_FLAG, PM_GET_CHIPID); 527 528 return pm_ipi_send_sync(primary_proc, payload, value, 2); 529 } 530