1 /* 2 * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. 3 * Copyright (c) 2022-2023, 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 uint32_t pm_get_shutdown_scope(void) 36 { 37 return pm_shutdown_scope; 38 } 39 40 /* PM API functions */ 41 42 /** 43 * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as 44 * wake sources in the XilPM. 45 * @node_id: Node id of processor 46 */ 47 void pm_client_set_wakeup_sources(uint32_t node_id) 48 { 49 uint32_t reg_num, device_id; 50 uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX] = {0U}; 51 uint32_t isenabler1 = PLAT_GICD_BASE_VALUE + GICD_ISENABLER + 4U; 52 53 zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set)); 54 55 for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) { 56 uint32_t base_irq = reg_num << ISENABLER_SHIFT; 57 uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2)); 58 59 if (reg == 0U) { 60 continue; 61 } 62 63 while (reg != 0U) { 64 enum pm_device_node_idx node_idx; 65 uint32_t idx, irq, lowest_set = reg & (-reg); 66 enum pm_ret_status ret; 67 68 idx = (uint32_t)__builtin_ctz(lowest_set); 69 irq = base_irq + idx; 70 71 if (irq > IRQ_MAX) { 72 break; 73 } 74 75 node_idx = irq_to_pm_node_idx(irq); 76 reg &= ~lowest_set; 77 78 if (node_idx > XPM_NODEIDX_DEV_MIN) { 79 if (pm_wakeup_nodes_set[node_idx] == 0U) { 80 /* Get device ID from node index */ 81 device_id = PERIPH_DEVID((uint32_t)node_idx); 82 ret = pm_set_wakeup_source(node_id, 83 device_id, 1U, 84 SECURE_FLAG); 85 pm_wakeup_nodes_set[node_idx] = (ret == PM_RET_SUCCESS) ? 86 1U : 0U; 87 } 88 } 89 } 90 } 91 } 92 93 /** 94 * pm_handle_eemi_call() - PM call for processor to send eemi payload 95 * @flag 0 - Call from secure source 96 * 1 - Call from non-secure source 97 * @x0 to x5 Arguments received per SMC64 standard 98 * @result Payload received from firmware 99 * 100 * @return PM_RET_SUCCESS on success or error code 101 */ 102 enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1, 103 uint32_t x2, uint32_t x3, uint32_t x4, 104 uint32_t x5, uint64_t *result) 105 { 106 uint32_t payload[PAYLOAD_ARG_CNT] = {0}; 107 uint32_t module_id; 108 109 module_id = (x0 & MODULE_ID_MASK) >> 8U; 110 111 //default module id is for LIBPM 112 if (module_id == 0) { 113 module_id = LIBPM_MODULE_ID; 114 } 115 116 PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5); 117 return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT); 118 } 119 120 /** 121 * pm_self_suspend() - PM call for processor to suspend itself 122 * @nid Node id of the processor or subsystem 123 * @latency Requested maximum wakeup latency (not supported) 124 * @state Requested state 125 * @address Resume address 126 * @flag 0 - Call from secure source 127 * 1 - Call from non-secure source 128 * 129 * This is a blocking call, it will return only once PMU has responded. 130 * On a wakeup, resume address will be automatically set by PMU. 131 * 132 * @return Returns status, either success or error+reason 133 */ 134 enum pm_ret_status pm_self_suspend(uint32_t nid, 135 uint32_t latency, 136 uint32_t state, 137 uintptr_t address, uint32_t flag) 138 { 139 uint32_t payload[PAYLOAD_ARG_CNT]; 140 uint32_t cpuid = plat_my_core_pos(); 141 const struct pm_proc *proc = pm_get_proc(cpuid); 142 143 if (proc == NULL) { 144 WARN("Failed to get proc %d\n", cpuid); 145 return PM_RET_ERROR_INTERNAL; 146 } 147 148 /* 149 * Do client specific suspend operations 150 * (e.g. set powerdown request bit) 151 */ 152 pm_client_suspend(proc, state); 153 154 /* Send request to the PLM */ 155 PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND, 156 proc->node_id, latency, state, address, 157 (address >> 32)); 158 return pm_ipi_send_sync(proc, payload, NULL, 0); 159 } 160 161 /** 162 * pm_abort_suspend() - PM call to announce that a prior suspend request 163 * is to be aborted. 164 * @reason Reason for the abort 165 * @flag 0 - Call from secure source 166 * 1 - Call from non-secure source 167 * 168 * Calling PU expects the PMU to abort the initiated suspend procedure. 169 * This is a non-blocking call without any acknowledge. 170 * 171 * @return Returns status, either success or error+reason 172 */ 173 enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag) 174 { 175 uint32_t payload[PAYLOAD_ARG_CNT]; 176 177 /* 178 * Do client specific abort suspend operations 179 * (e.g. enable interrupts and clear powerdown request bit) 180 */ 181 pm_client_abort_suspend(); 182 183 /* Send request to the PLM */ 184 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND, 185 reason, primary_proc->node_id); 186 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 187 } 188 189 /** 190 * pm_req_suspend() - PM call to request for another PU or subsystem to 191 * be suspended gracefully. 192 * @target Node id of the targeted PU or subsystem 193 * @ack Flag to specify whether acknowledge is requested 194 * @latency Requested wakeup latency (not supported) 195 * @state Requested state (not supported) 196 * @flag 0 - Call from secure source 197 * 1 - Call from non-secure source 198 * 199 * @return Returns status, either success or error+reason 200 */ 201 enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, 202 uint32_t latency, uint32_t state, 203 uint32_t flag) 204 { 205 uint32_t payload[PAYLOAD_ARG_CNT]; 206 207 /* Send request to the PMU */ 208 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target, 209 latency, state); 210 if (ack == IPI_BLOCKING) { 211 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 212 } else { 213 return pm_ipi_send(primary_proc, payload); 214 } 215 } 216 217 /** 218 * pm_req_wakeup() - PM call for processor to wake up selected processor 219 * or subsystem 220 * @target Device ID of the processor or subsystem to wake up 221 * @set_address Resume address presence indicator 222 * 1 - resume address specified, 0 - otherwise 223 * @address Resume address 224 * @ack Flag to specify whether acknowledge requested 225 * @flag 0 - Call from secure source 226 * 1 - Call from non-secure source 227 * 228 * This API function is either used to power up another APU core for SMP 229 * (by PSCI) or to power up an entirely different PU or subsystem, such 230 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be 231 * automatically set by PMC. 232 * 233 * @return Returns status, either success or error+reason 234 */ 235 enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, 236 uintptr_t address, uint8_t ack, uint32_t flag) 237 { 238 uint32_t payload[PAYLOAD_ARG_CNT]; 239 240 /* Send request to the PMC to perform the wake of the PU */ 241 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target, 242 set_address, address, ack); 243 244 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 245 } 246 247 /** 248 * pm_get_callbackdata() - Read from IPI response buffer 249 * @data - array of PAYLOAD_ARG_CNT elements 250 * @flag - 0 - Call from secure source 251 * 1 - Call from non-secure source 252 * @ack - 0 - Do not ack IPI after reading payload 253 * 1 - Ack IPI after reading payload 254 * 255 * Read value from ipi buffer response buffer. 256 * @return Returns status, either success or error 257 */ 258 enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack) 259 { 260 enum pm_ret_status ret = PM_RET_SUCCESS; 261 /* Return if interrupt is not from PMU */ 262 if (pm_ipi_irq_status(primary_proc) == 0) { 263 return ret; 264 } 265 266 ret = pm_ipi_buff_read_callb(data, count); 267 268 if (ack != 0U) { 269 pm_ipi_irq_clear(primary_proc); 270 } 271 272 return ret; 273 } 274 275 /** 276 * pm_pll_set_param() - Set PLL parameter 277 * 278 * This API is deprecated and maintained here for backward compatibility. 279 * New use of this API should be avoided for versal platform. 280 * This API and its use cases will be removed for versal platform. 281 * 282 * @clk_id PLL clock ID 283 * @param PLL parameter ID 284 * @value Value to set for PLL parameter 285 * @flag 0 - Call from secure source 286 * 1 - Call from non-secure source 287 * 288 * @return Returns status, either success or error+reason 289 */ 290 enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, 291 uint32_t value, uint32_t flag) 292 { 293 uint32_t payload[PAYLOAD_ARG_CNT]; 294 295 /* Send request to the PMC */ 296 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER, 297 clk_id, param, value); 298 299 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 300 } 301 302 /** 303 * pm_pll_get_param() - Get PLL parameter value 304 * 305 * This API is deprecated and maintained here for backward compatibility. 306 * New use of this API should be avoided for versal platform. 307 * This API and its use cases will be removed for versal platform. 308 * 309 * @clk_id PLL clock ID 310 * @param PLL parameter ID 311 * @value: Buffer to store PLL parameter value 312 * @flag 0 - Call from secure source 313 * 1 - Call from non-secure source 314 * 315 * @return Returns status, either success or error+reason 316 */ 317 enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, 318 uint32_t *value, uint32_t flag) 319 { 320 uint32_t payload[PAYLOAD_ARG_CNT]; 321 322 /* Send request to the PMC */ 323 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER, 324 clk_id, param); 325 326 return pm_ipi_send_sync(primary_proc, payload, value, 1); 327 } 328 329 /** 330 * pm_pll_set_mode() - Set PLL mode 331 * 332 * This API is deprecated and maintained here for backward compatibility. 333 * New use of this API should be avoided for versal platform. 334 * This API and its use cases will be removed for versal platform. 335 * 336 * @clk_id PLL clock ID 337 * @mode PLL mode 338 * @flag 0 - Call from secure source 339 * 1 - Call from non-secure source 340 * 341 * @return Returns status, either success or error+reason 342 */ 343 enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode, 344 uint32_t flag) 345 { 346 uint32_t payload[PAYLOAD_ARG_CNT]; 347 348 /* Send request to the PMC */ 349 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE, 350 clk_id, mode); 351 352 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 353 } 354 355 /** 356 * pm_pll_get_mode() - Get PLL mode 357 * 358 * This API is deprecated and maintained here for backward compatibility. 359 * New use of this API should be avoided for versal platform. 360 * This API and its use cases will be removed for versal platform. 361 * 362 * @clk_id PLL clock ID 363 * @mode: Buffer to store PLL mode 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 enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode, 370 uint32_t flag) 371 { 372 uint32_t payload[PAYLOAD_ARG_CNT]; 373 374 /* Send request to the PMC */ 375 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE, 376 clk_id); 377 378 return pm_ipi_send_sync(primary_proc, payload, mode, 1); 379 } 380 381 /** 382 * pm_force_powerdown() - PM call to request for another PU or subsystem to 383 * be powered down forcefully 384 * @target Device ID of the PU node to be forced powered down. 385 * @ack Flag to specify whether acknowledge is requested 386 * @flag 0 - Call from secure source 387 * 1 - Call from non-secure source 388 * 389 * @return Returns status, either success or error+reason 390 */ 391 enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack, 392 uint32_t flag) 393 { 394 uint32_t payload[PAYLOAD_ARG_CNT]; 395 396 /* Send request to the PMC */ 397 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN, 398 target, ack); 399 400 if (ack == IPI_BLOCKING) { 401 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 402 } else { 403 return pm_ipi_send(primary_proc, payload); 404 } 405 } 406 407 /** 408 * pm_system_shutdown() - PM call to request a system shutdown or restart 409 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope 410 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system 411 * @flag 0 - Call from secure source 412 * 1 - Call from non-secure source 413 * 414 * @return Returns status, either success or error+reason 415 */ 416 enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, 417 uint32_t flag) 418 { 419 uint32_t payload[PAYLOAD_ARG_CNT]; 420 421 if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) { 422 /* Setting scope for subsequent PSCI reboot or shutdown */ 423 pm_shutdown_scope = subtype; 424 return PM_RET_SUCCESS; 425 } 426 427 /* Send request to the PMC */ 428 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN, 429 type, subtype); 430 431 return pm_ipi_send_non_blocking(primary_proc, payload); 432 } 433 434 /** 435 * pm_query_data() - PM API for querying firmware data 436 * 437 * This API is deprecated and maintained here for backward compatibility. 438 * New use of this API should be avoided for versal platform. 439 * This API and its use cases will be removed for versal platform. 440 * 441 * @qid The type of data to query 442 * @arg1 Argument 1 to requested query data call 443 * @arg2 Argument 2 to requested query data call 444 * @arg3 Argument 3 to requested query data call 445 * @data Returned output data 446 * @flag 0 - Call from secure source 447 * 1 - Call from non-secure source 448 * 449 * @retur - 0 if success else non-zero error code of type 450 * enum pm_ret_status 451 */ 452 enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, 453 uint32_t arg3, uint32_t *data, uint32_t flag) 454 { 455 uint32_t ret; 456 uint32_t version[PAYLOAD_ARG_CNT] = {0}; 457 uint32_t payload[PAYLOAD_ARG_CNT]; 458 uint32_t fw_api_version; 459 460 /* Send request to the PMC */ 461 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid, 462 arg1, arg2, arg3); 463 464 ret = pm_feature_check((uint32_t)PM_QUERY_DATA, &version[0], flag); 465 if (ret == PM_RET_SUCCESS) { 466 fw_api_version = version[0] & 0xFFFFU; 467 if ((fw_api_version == 2U) && 468 ((qid == XPM_QID_CLOCK_GET_NAME) || 469 (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) { 470 ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT); 471 if (ret == PM_RET_SUCCESS) { 472 ret = data[0]; 473 data[0] = data[1]; 474 data[1] = data[2]; 475 data[2] = data[3]; 476 } 477 } else { 478 ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT); 479 } 480 } 481 return ret; 482 } 483 /** 484 * pm_api_ioctl() - PM IOCTL API for device control and configs 485 * 486 * This API is deprecated and maintained here for backward compatibility. 487 * New use of this API should be avoided for versal platform. 488 * This API and its use cases will be removed for versal platform. 489 * 490 * @device_id Device ID 491 * @ioctl_id ID of the requested IOCTL 492 * @arg1 Argument 1 to requested IOCTL call 493 * @arg2 Argument 2 to requested IOCTL call 494 * @arg3 Argument 3 to requested IOCTL call 495 * @value Returned output value 496 * @flag 0 - Call from secure source 497 * 1 - Call from non-secure source 498 * 499 * This function calls IOCTL to firmware for device control and configuration. 500 * 501 * @return Returns status, either 0 on success or non-zero error code 502 * of type enum pm_ret_status 503 */ 504 enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, 505 uint32_t arg1, uint32_t arg2, uint32_t arg3, 506 uint32_t *value, uint32_t flag) 507 { 508 enum pm_ret_status ret; 509 510 switch (ioctl_id) { 511 case IOCTL_SET_PLL_FRAC_MODE: 512 ret = pm_pll_set_mode(arg1, arg2, flag); 513 break; 514 case IOCTL_GET_PLL_FRAC_MODE: 515 ret = pm_pll_get_mode(arg1, value, flag); 516 break; 517 case IOCTL_SET_PLL_FRAC_DATA: 518 ret = pm_pll_set_param(arg1, (uint32_t)PM_PLL_PARAM_DATA, arg2, flag); 519 break; 520 case IOCTL_GET_PLL_FRAC_DATA: 521 ret = pm_pll_get_param(arg1, (uint32_t)PM_PLL_PARAM_DATA, value, flag); 522 break; 523 case IOCTL_SET_SGI: 524 /* Get the sgi number */ 525 ret = pm_register_sgi(arg1, arg2); 526 if (ret != 0) { 527 return PM_RET_ERROR_ARGS; 528 } 529 ret = PM_RET_SUCCESS; 530 break; 531 default: 532 return PM_RET_ERROR_NOTSUPPORTED; 533 } 534 535 return ret; 536 } 537 538 /** 539 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended 540 * @target Device id of the targeted PU or subsystem 541 * @wkup_node Device id of the wakeup peripheral 542 * @enable Enable or disable the specified peripheral as wake source 543 * @flag 0 - Call from secure source 544 * 1 - Call from non-secure source 545 * 546 * @return Returns status, either success or error+reason 547 */ 548 enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, 549 uint8_t enable, uint32_t flag) 550 { 551 uint32_t payload[PAYLOAD_ARG_CNT]; 552 553 PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE, 554 target, wkup_device, enable); 555 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 556 } 557 558 /** 559 * pm_feature_check() - Returns the supported API version if supported 560 * @api_id API ID to check 561 * @flag 0 - Call from secure source 562 * 1 - Call from non-secure source 563 * @ret_payload pointer to array of PAYLOAD_ARG_CNT number of 564 * words Returned supported API version and bitmasks 565 * for IOCTL and QUERY ID 566 * 567 * @return Returns status, either success or error+reason 568 */ 569 enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload, 570 uint32_t flag) 571 { 572 uint32_t payload[PAYLOAD_ARG_CNT]; 573 uint32_t module_id; 574 575 /* Return version of API which are implemented in ATF only */ 576 switch (api_id) { 577 case PM_GET_CALLBACK_DATA: 578 case PM_GET_TRUSTZONE_VERSION: 579 ret_payload[0] = PM_API_VERSION_2; 580 return PM_RET_SUCCESS; 581 case TF_A_PM_REGISTER_SGI: 582 ret_payload[0] = PM_API_BASE_VERSION; 583 return PM_RET_SUCCESS; 584 default: 585 break; 586 } 587 588 module_id = (api_id & MODULE_ID_MASK) >> 8U; 589 590 /* 591 * feature check should be done only for LIBPM module 592 * If module_id is 0, then we consider it LIBPM module as default id 593 */ 594 if ((module_id > 0) && (module_id != LIBPM_MODULE_ID)) { 595 return PM_RET_SUCCESS; 596 } 597 598 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, 599 PM_FEATURE_CHECK, api_id); 600 return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT); 601 } 602 603 /** 604 * pm_load_pdi() - Load the PDI 605 * 606 * This function provides support to load PDI from linux 607 * 608 * src: Source device of pdi(DDR, OCM, SD etc) 609 * address_low: lower 32-bit Linear memory space address 610 * address_high: higher 32-bit Linear memory space address 611 * @flag 0 - Call from secure source 612 * 1 - Call from non-secure source 613 * 614 * @return Returns status, either success or error+reason 615 */ 616 enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, 617 uint32_t address_high, uint32_t flag) 618 { 619 uint32_t payload[PAYLOAD_ARG_CNT]; 620 621 /* Send request to the PMU */ 622 PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src, 623 address_high, address_low); 624 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 625 } 626 627 /** 628 * pm_register_notifier() - PM call to register a subsystem to be notified 629 * about the device event 630 * @device_id Device ID for the Node to which the event is related 631 * @event Event in question 632 * @wake Wake subsystem upon capturing the event if value 1 633 * @enable Enable the registration for value 1, disable for value 0 634 * @flag 0 - Call from secure source 635 * 1 - Call from non-secure source 636 * 637 * @return Returns status, either success or error+reason 638 */ 639 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, 640 uint32_t wake, uint32_t enable, 641 uint32_t flag) 642 { 643 uint32_t payload[PAYLOAD_ARG_CNT]; 644 645 /* Send request to the PMC */ 646 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER, 647 device_id, event, wake, enable); 648 649 return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 650 } 651 652 /** 653 * pm_get_chipid() - Read silicon ID registers 654 * @value: Buffer for two 32bit words. 655 * 656 * @return: Returns status, either success or error+reason and, 657 * optionally, @value. 658 */ 659 enum pm_ret_status pm_get_chipid(uint32_t *value) 660 { 661 uint32_t payload[PAYLOAD_ARG_CNT]; 662 663 PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, SECURE_FLAG, PM_GET_CHIPID); 664 665 return pm_ipi_send_sync(primary_proc, payload, value, 2); 666 } 667