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