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