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