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