1 /* 2 * Copyright (c) 2018-2022, Arm Limited and Contributors. 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 * ZynqMP system level PM-API functions for ioctl. 10 */ 11 12 #include <arch_helpers.h> 13 #include <drivers/delay_timer.h> 14 #include <lib/mmio.h> 15 #include <plat/common/platform.h> 16 17 #include "pm_api_clock.h" 18 #include "pm_api_ioctl.h" 19 #include "pm_client.h" 20 #include "pm_common.h" 21 #include "pm_ipi.h" 22 #include <zynqmp_def.h> 23 #include "zynqmp_pm_api_sys.h" 24 25 /** 26 * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode. 27 * @mode: Buffer to store value of oper mode(Split/Lock-step) 28 * 29 * This function provides current configured RPU operational mode. 30 * 31 * Return: Returns status, either success or error+reason. 32 * 33 */ 34 static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(uint32_t *mode) 35 { 36 uint32_t val; 37 38 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 39 val &= ZYNQMP_SLSPLIT_MASK; 40 if (val == 0U) { 41 *mode = PM_RPU_MODE_LOCKSTEP; 42 } else { 43 *mode = PM_RPU_MODE_SPLIT; 44 } 45 46 return PM_RET_SUCCESS; 47 } 48 49 /** 50 * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode. 51 * @mode: Value to set for oper mode(Split/Lock-step). 52 * 53 * This function configures RPU operational mode(Split/Lock-step). 54 * It also sets TCM combined mode in RPU lock-step and TCM non-combined 55 * mode for RPU split mode. In case of Lock step mode, RPU1's output is 56 * clamped. 57 * 58 * Return: Returns status, either success or error+reason. 59 * 60 */ 61 static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(uint32_t mode) 62 { 63 uint32_t val; 64 enum pm_ret_status status = PM_RET_SUCCESS; 65 66 if ((mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) != 0U) { 67 status = PM_RET_ERROR_ACCESS; 68 goto exit_label; 69 } 70 71 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 72 73 if (mode == PM_RPU_MODE_SPLIT) { 74 val |= ZYNQMP_SLSPLIT_MASK; 75 val &= ~ZYNQMP_TCM_COMB_MASK; 76 val &= ~ZYNQMP_SLCLAMP_MASK; 77 } else if (mode == PM_RPU_MODE_LOCKSTEP) { 78 val &= ~ZYNQMP_SLSPLIT_MASK; 79 val |= ZYNQMP_TCM_COMB_MASK; 80 val |= ZYNQMP_SLCLAMP_MASK; 81 } else { 82 status = PM_RET_ERROR_ARGS; 83 goto exit_label; 84 } 85 86 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); 87 88 exit_label: 89 return status; 90 } 91 92 /** 93 * pm_ioctl_config_boot_addr() - Configure RPU boot address. 94 * @nid: Node ID of RPU. 95 * @value: Value to set for boot address (TCM/OCM). 96 * 97 * This function configures RPU boot address(memory). 98 * 99 * Return: Returns status, either success or error+reason. 100 * 101 */ 102 static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid, 103 uint32_t value) 104 { 105 uint32_t rpu_cfg_addr, val; 106 107 if (nid == NODE_RPU_0) { 108 rpu_cfg_addr = ZYNQMP_RPU0_CFG; 109 } else if (nid == NODE_RPU_1) { 110 rpu_cfg_addr = ZYNQMP_RPU1_CFG; 111 } else { 112 return PM_RET_ERROR_ARGS; 113 } 114 115 val = mmio_read_32(rpu_cfg_addr); 116 117 if (value == PM_RPU_BOOTMEM_LOVEC) { 118 val &= ~ZYNQMP_VINITHI_MASK; 119 } else if (value == PM_RPU_BOOTMEM_HIVEC) { 120 val |= ZYNQMP_VINITHI_MASK; 121 } else { 122 return PM_RET_ERROR_ARGS; 123 } 124 125 mmio_write_32(rpu_cfg_addr, val); 126 127 return PM_RET_SUCCESS; 128 } 129 130 /** 131 * pm_ioctl_config_tcm_comb() - Configure TCM combined mode. 132 * @value: Value to set (Split/Combined). 133 * 134 * This function configures TCM to be in split mode or combined 135 * mode. 136 * 137 * Return: Returns status, either success or error+reason. 138 * 139 */ 140 static enum pm_ret_status pm_ioctl_config_tcm_comb(uint32_t value) 141 { 142 uint32_t val; 143 enum pm_ret_status status = PM_RET_SUCCESS; 144 145 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 146 147 if (value == PM_RPU_TCM_SPLIT) { 148 val &= ~ZYNQMP_TCM_COMB_MASK; 149 } else if (value == PM_RPU_TCM_COMB) { 150 val |= ZYNQMP_TCM_COMB_MASK; 151 } else { 152 status = PM_RET_ERROR_ARGS; 153 goto exit_label; 154 } 155 156 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); 157 158 exit_label: 159 return status; 160 } 161 162 /** 163 * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass. 164 * @type: Type of tap delay to enable/disable (e.g. QSPI). 165 * @value: Enable/Disable. 166 * 167 * This function enable/disable tap delay bypass. 168 * 169 * Return: Returns status, either success or error+reason. 170 * 171 */ 172 static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(uint32_t type, 173 uint32_t value) 174 { 175 enum pm_ret_status status = PM_RET_SUCCESS; 176 177 if ((((value != PM_TAPDELAY_BYPASS_ENABLE) && 178 (value != PM_TAPDELAY_BYPASS_DISABLE)) || (type >= PM_TAPDELAY_MAX))) { 179 status = PM_RET_ERROR_ARGS; 180 } else { 181 status = pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type); 182 } 183 184 return status; 185 } 186 187 /** 188 * pm_ioctl_sd_dll_reset() - Reset DLL logic. 189 * @nid: Node ID of the device. 190 * @type: Reset type. 191 * 192 * This function resets DLL logic for the SD device. 193 * 194 * Return: Returns status, either success or error+reason. 195 * 196 */ 197 static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid, 198 uint32_t type) 199 { 200 uint32_t mask, val; 201 enum pm_ret_status ret; 202 203 if (nid == NODE_SD_0) { 204 mask = ZYNQMP_SD0_DLL_RST_MASK; 205 val = ZYNQMP_SD0_DLL_RST; 206 } else if (nid == NODE_SD_1) { 207 mask = ZYNQMP_SD1_DLL_RST_MASK; 208 val = ZYNQMP_SD1_DLL_RST; 209 } else { 210 return PM_RET_ERROR_ARGS; 211 } 212 213 switch (type) { 214 case PM_DLL_RESET_ASSERT: 215 case PM_DLL_RESET_PULSE: 216 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val); 217 if (ret != PM_RET_SUCCESS) { 218 return ret; 219 } 220 221 if (type == PM_DLL_RESET_ASSERT) { 222 break; 223 } 224 mdelay(1); 225 /* Fallthrough */ 226 case PM_DLL_RESET_RELEASE: 227 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0); 228 break; 229 default: 230 ret = PM_RET_ERROR_ARGS; 231 break; 232 } 233 234 return ret; 235 } 236 237 /** 238 * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device. 239 * @nid: Node ID of the device. 240 * @type: Type of tap delay to set (input/output). 241 * @value: Value to set fot the tap delay. 242 * 243 * This function sets input/output tap delay for the SD device. 244 * 245 * Return: Returns status, either success or error+reason. 246 * 247 */ 248 static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, 249 enum tap_delay_type type, 250 uint32_t value) 251 { 252 uint32_t shift; 253 enum pm_ret_status ret; 254 uint32_t val, mask; 255 256 if (nid == NODE_SD_0) { 257 shift = 0; 258 mask = ZYNQMP_SD0_DLL_RST_MASK; 259 } else if (nid == NODE_SD_1) { 260 shift = ZYNQMP_SD_TAP_OFFSET; 261 mask = ZYNQMP_SD1_DLL_RST_MASK; 262 } else { 263 return PM_RET_ERROR_ARGS; 264 } 265 266 ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val); 267 if (ret != PM_RET_SUCCESS) { 268 return ret; 269 } 270 271 if ((val & mask) == 0U) { 272 ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT); 273 if (ret != PM_RET_SUCCESS) { 274 return ret; 275 } 276 } 277 278 if (type == PM_TAPDELAY_INPUT) { 279 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 280 (uint64_t)(ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 281 (ZYNQMP_SD_ITAPCHGWIN << shift)); 282 283 if (ret != PM_RET_SUCCESS) { 284 goto reset_release; 285 } 286 287 if (value == 0U) { 288 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 289 (uint64_t)(ZYNQMP_SD_ITAPDLYENA_MASK << 290 shift), 0); 291 } else { 292 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 293 (uint64_t)(ZYNQMP_SD_ITAPDLYENA_MASK << 294 shift), (uint64_t)(ZYNQMP_SD_ITAPDLYENA << 295 shift)); 296 } 297 298 if (ret != PM_RET_SUCCESS) { 299 goto reset_release; 300 } 301 302 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 303 (uint64_t)(ZYNQMP_SD_ITAPDLYSEL_MASK << shift), 304 (value << shift)); 305 306 if (ret != PM_RET_SUCCESS) { 307 goto reset_release; 308 } 309 310 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 311 (uint64_t)(ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0); 312 } else if (type == PM_TAPDELAY_OUTPUT) { 313 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, 314 (uint64_t)(ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0); 315 316 if (ret != PM_RET_SUCCESS) { 317 goto reset_release; 318 } 319 320 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, 321 (uint64_t)(ZYNQMP_SD_OTAPDLYSEL_MASK << shift), 322 (value << shift)); 323 } else { 324 ret = PM_RET_ERROR_ARGS; 325 } 326 327 reset_release: 328 if ((val & mask) == 0) { 329 (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE); 330 } 331 332 return ret; 333 } 334 335 /** 336 * pm_ioctl_set_pll_frac_mode() - Ioctl function for setting pll mode. 337 * @pll: PLL clock id. 338 * @mode: Mode fraction/integar. 339 * 340 * This function sets PLL mode. 341 * 342 * Return: Returns status, either success or error+reason. 343 * 344 */ 345 static enum pm_ret_status pm_ioctl_set_pll_frac_mode 346 (uint32_t pll, uint32_t mode) 347 { 348 return pm_clock_set_pll_mode(pll, mode); 349 } 350 351 /** 352 * pm_ioctl_get_pll_frac_mode() - Ioctl function for getting pll mode. 353 * @pll: PLL clock id. 354 * @mode: Mode fraction/integar. 355 * 356 * This function return current PLL mode. 357 * 358 * Return: Returns status, either success or error+reason. 359 * 360 */ 361 static enum pm_ret_status pm_ioctl_get_pll_frac_mode 362 (uint32_t pll, uint32_t *mode) 363 { 364 return pm_clock_get_pll_mode(pll, mode); 365 } 366 367 /** 368 * pm_ioctl_set_pll_frac_data() - Ioctl function for setting pll fraction data. 369 * @pll: PLL clock id. 370 * @data: fraction data. 371 * 372 * This function sets fraction data. 373 * It is valid for fraction mode only. 374 * 375 * Return: Returns status, either success or error+reason. 376 * 377 */ 378 static enum pm_ret_status pm_ioctl_set_pll_frac_data 379 (uint32_t pll, uint32_t data) 380 { 381 enum pm_node_id pll_nid; 382 enum pm_ret_status status; 383 384 /* Get PLL node ID using PLL clock ID */ 385 status = pm_clock_get_pll_node_id(pll, &pll_nid); 386 if (status == PM_RET_SUCCESS) { 387 status = pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data); 388 } 389 390 return status; 391 } 392 393 /** 394 * pm_ioctl_get_pll_frac_data() - Ioctl function for getting pll fraction data. 395 * @pll: PLL clock id. 396 * @data: fraction data. 397 * 398 * This function returns fraction data value. 399 * 400 * Return: Returns status, either success or error+reason. 401 * 402 */ 403 static enum pm_ret_status pm_ioctl_get_pll_frac_data 404 (uint32_t pll, uint32_t *data) 405 { 406 enum pm_node_id pll_nid; 407 enum pm_ret_status status; 408 409 /* Get PLL node ID using PLL clock ID */ 410 status = pm_clock_get_pll_node_id(pll, &pll_nid); 411 if (status == PM_RET_SUCCESS) { 412 status = pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data); 413 } 414 415 return status; 416 } 417 418 /** 419 * pm_ioctl_write_ggs() - Ioctl function for writing global general storage 420 * (ggs). 421 * @index: GGS register index. 422 * @value: Register value to be written. 423 * 424 * This function writes value to GGS register. 425 * 426 * Return: Returns status, either success or error+reason. 427 * 428 */ 429 static enum pm_ret_status pm_ioctl_write_ggs(uint32_t index, 430 uint32_t value) 431 { 432 enum pm_ret_status ret_status = PM_RET_SUCCESS; 433 434 if (index >= GGS_NUM_REGS) { 435 ret_status = PM_RET_ERROR_ARGS; 436 } else { 437 ret_status = pm_mmio_write((uint64_t)GGS_BASEADDR + (index << 2), 438 0xFFFFFFFFU, value); 439 } 440 441 return ret_status; 442 } 443 444 /** 445 * pm_ioctl_read_ggs() - Ioctl function for reading global general storage 446 * (ggs). 447 * @index: GGS register index. 448 * @value: Register value. 449 * 450 * This function returns GGS register value. 451 * 452 * Return: Returns status, either success or error+reason. 453 * 454 */ 455 static enum pm_ret_status pm_ioctl_read_ggs(uint32_t index, 456 uint32_t *value) 457 { 458 enum pm_ret_status ret_status = PM_RET_SUCCESS; 459 460 if (index >= GGS_NUM_REGS) { 461 ret_status = PM_RET_ERROR_ARGS; 462 } else { 463 ret_status = pm_mmio_read((uint64_t)GGS_BASEADDR + (index << 2), value); 464 } 465 466 return ret_status; 467 } 468 469 /** 470 * pm_ioctl_write_pggs() - Ioctl function for writing persistent global general 471 * storage (pggs). 472 * @index: PGGS register index. 473 * @value: Register value to be written. 474 * 475 * This function writes value to PGGS register. 476 * 477 * Return: Returns status, either success or error+reason. 478 * 479 */ 480 static enum pm_ret_status pm_ioctl_write_pggs(uint32_t index, 481 uint32_t value) 482 { 483 enum pm_ret_status ret_status = PM_RET_SUCCESS; 484 485 if (index >= PGGS_NUM_REGS) { 486 ret_status = PM_RET_ERROR_ARGS; 487 } else { 488 ret_status = pm_mmio_write((uint64_t)PGGS_BASEADDR + (index << 2), 489 0xFFFFFFFFU, value); 490 } 491 492 return ret_status; 493 } 494 495 /** 496 * pm_ioctl_afi() - Ioctl function for writing afi values. 497 * @index: AFI register index. 498 * @value: Register value to be written. 499 * 500 * Return: Returns status, either success or error+reason. 501 * 502 */ 503 static enum pm_ret_status pm_ioctl_afi(uint32_t index, 504 uint32_t value) 505 { 506 uint32_t mask; 507 enum pm_ret_status status = PM_RET_ERROR_ARGS; 508 const uint32_t regarr[] = {0xFD360000U, 509 0xFD360014U, 510 0xFD370000U, 511 0xFD370014U, 512 0xFD380000U, 513 0xFD380014U, 514 0xFD390000U, 515 0xFD390014U, 516 0xFD3a0000U, 517 0xFD3a0014U, 518 0xFD3b0000U, 519 0xFD3b0014U, 520 0xFF9b0000U, 521 0xFF9b0014U, 522 0xFD615000U, 523 0xFF419000U, 524 }; 525 526 if (index < ARRAY_SIZE(regarr)) { 527 if (index <= AFIFM6_WRCTRL) { 528 mask = FABRIC_WIDTH; 529 } else { 530 mask = 0xf00; 531 } 532 status = pm_mmio_write(regarr[index], mask, value); 533 } 534 535 return status; 536 } 537 538 /** 539 * pm_ioctl_read_pggs() - Ioctl function for reading persistent global general 540 * storage (pggs). 541 * @index: PGGS register index. 542 * @value: Register value. 543 * 544 * This function returns PGGS register value. 545 * 546 * Return: Returns status, either success or error+reason. 547 * 548 */ 549 static enum pm_ret_status pm_ioctl_read_pggs(uint32_t index, 550 uint32_t *value) 551 { 552 enum pm_ret_status status = 0; 553 554 if (index >= PGGS_NUM_REGS) { 555 status = PM_RET_ERROR_ARGS; 556 } else { 557 status = pm_mmio_read((uint64_t)PGGS_BASEADDR + (index << 2), value); 558 } 559 560 return status; 561 } 562 563 /** 564 * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset. 565 * 566 * Return: Returns status, either success or error+reason. 567 * 568 * This function peerforms the ULPI reset sequence for resetting 569 * the ULPI transceiver. 570 */ 571 static enum pm_ret_status pm_ioctl_ulpi_reset(void) 572 { 573 enum pm_ret_status ret; 574 575 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 576 ZYNQMP_ULPI_RESET_VAL_HIGH); 577 if (ret != PM_RET_SUCCESS) { 578 goto exit_label; 579 } 580 581 /* Drive ULPI assert for atleast 1ms */ 582 mdelay(1); 583 584 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 585 ZYNQMP_ULPI_RESET_VAL_LOW); 586 if (ret != PM_RET_SUCCESS) { 587 goto exit_label; 588 } 589 590 /* Drive ULPI de-assert for atleast 1ms */ 591 mdelay(1); 592 593 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 594 ZYNQMP_ULPI_RESET_VAL_HIGH); 595 596 exit_label: 597 return ret; 598 } 599 600 /** 601 * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status. 602 * @value: Value to write. 603 * 604 * This function sets healthy bit value to indicate boot health status 605 * to firmware. 606 * 607 * Return: Returns status, either success or error+reason. 608 * 609 */ 610 static enum pm_ret_status pm_ioctl_set_boot_health_status(uint32_t value) 611 { 612 return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4, 613 PM_BOOT_HEALTH_STATUS_MASK, value); 614 } 615 616 /** 617 * pm_api_ioctl() - PM IOCTL API for device control and configs. 618 * @nid: Node ID of the device. 619 * @ioctl_id: ID of the requested IOCTL. 620 * @arg1: Argument 1 to requested IOCTL call. 621 * @arg2: Argument 2 to requested IOCTL call. 622 * @value: Returned output value. 623 * 624 * This function calls IOCTL to firmware for device control and configuration. 625 * 626 * Return: Returns status, either success or error+reason. 627 * 628 */ 629 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, 630 uint32_t ioctl_id, 631 uint32_t arg1, 632 uint32_t arg2, 633 uint32_t *value) 634 { 635 enum pm_ret_status ret; 636 uint32_t payload[PAYLOAD_ARG_CNT]; 637 638 switch (ioctl_id) { 639 case IOCTL_GET_RPU_OPER_MODE: 640 ret = pm_ioctl_get_rpu_oper_mode(value); 641 break; 642 case IOCTL_SET_RPU_OPER_MODE: 643 ret = pm_ioctl_set_rpu_oper_mode(arg1); 644 break; 645 case IOCTL_RPU_BOOT_ADDR_CONFIG: 646 ret = pm_ioctl_config_boot_addr(nid, arg1); 647 break; 648 case IOCTL_TCM_COMB_CONFIG: 649 ret = pm_ioctl_config_tcm_comb(arg1); 650 break; 651 case IOCTL_SET_TAPDELAY_BYPASS: 652 ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2); 653 break; 654 case IOCTL_SD_DLL_RESET: 655 ret = pm_ioctl_sd_dll_reset(nid, arg1); 656 break; 657 case IOCTL_SET_SD_TAPDELAY: 658 ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2); 659 break; 660 case IOCTL_SET_PLL_FRAC_MODE: 661 ret = pm_ioctl_set_pll_frac_mode(arg1, arg2); 662 break; 663 case IOCTL_GET_PLL_FRAC_MODE: 664 ret = pm_ioctl_get_pll_frac_mode(arg1, value); 665 break; 666 case IOCTL_SET_PLL_FRAC_DATA: 667 ret = pm_ioctl_set_pll_frac_data(arg1, arg2); 668 break; 669 case IOCTL_GET_PLL_FRAC_DATA: 670 ret = pm_ioctl_get_pll_frac_data(arg1, value); 671 break; 672 case IOCTL_WRITE_GGS: 673 ret = pm_ioctl_write_ggs(arg1, arg2); 674 break; 675 case IOCTL_READ_GGS: 676 ret = pm_ioctl_read_ggs(arg1, value); 677 break; 678 case IOCTL_WRITE_PGGS: 679 ret = pm_ioctl_write_pggs(arg1, arg2); 680 break; 681 case IOCTL_READ_PGGS: 682 ret = pm_ioctl_read_pggs(arg1, value); 683 break; 684 case IOCTL_ULPI_RESET: 685 ret = pm_ioctl_ulpi_reset(); 686 break; 687 case IOCTL_SET_BOOT_HEALTH_STATUS: 688 ret = pm_ioctl_set_boot_health_status(arg1); 689 break; 690 case IOCTL_AFI: 691 ret = pm_ioctl_afi(arg1, arg2); 692 break; 693 default: 694 /* Send request to the PMU */ 695 PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2); 696 697 ret = pm_ipi_send_sync(primary_proc, payload, value, 1); 698 break; 699 } 700 701 return ret; 702 } 703 704 /** 705 * tfa_ioctl_bitmask() - API to get supported IOCTL ID mask. 706 * @bit_mask: Returned bit mask of supported IOCTL IDs. 707 * 708 * Return: 0 success, negative value for errors. 709 * 710 */ 711 enum pm_ret_status tfa_ioctl_bitmask(uint32_t *bit_mask) 712 { 713 const uint8_t supported_ids[] = { 714 IOCTL_GET_RPU_OPER_MODE, 715 IOCTL_SET_RPU_OPER_MODE, 716 IOCTL_RPU_BOOT_ADDR_CONFIG, 717 IOCTL_TCM_COMB_CONFIG, 718 IOCTL_SET_TAPDELAY_BYPASS, 719 IOCTL_SD_DLL_RESET, 720 IOCTL_SET_SD_TAPDELAY, 721 IOCTL_SET_PLL_FRAC_MODE, 722 IOCTL_GET_PLL_FRAC_MODE, 723 IOCTL_SET_PLL_FRAC_DATA, 724 IOCTL_GET_PLL_FRAC_DATA, 725 IOCTL_WRITE_GGS, 726 IOCTL_READ_GGS, 727 IOCTL_WRITE_PGGS, 728 IOCTL_READ_PGGS, 729 IOCTL_ULPI_RESET, 730 IOCTL_SET_BOOT_HEALTH_STATUS, 731 IOCTL_AFI, 732 }; 733 uint8_t i, ioctl_id; 734 enum pm_ret_status ret = PM_RET_SUCCESS; 735 736 for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) { 737 ioctl_id = supported_ids[i]; 738 if (ioctl_id >= 64U) { 739 ret = PM_RET_ERROR_NOTSUPPORTED; 740 break; 741 } 742 ret = check_api_dependency(ioctl_id); 743 if (ret == PM_RET_SUCCESS) { 744 bit_mask[ioctl_id / 32U] |= BIT(ioctl_id % 32U); 745 } 746 } 747 748 return ret; 749 } 750