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 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 return pm_api_clk_set_pll_frac_data(pll, data); 379 } 380 381 /** 382 * pm_ioctl_get_pll_frac_data() - Ioctl function for 383 * getting pll fraction data 384 * @pll PLL clock id 385 * @data fraction data 386 * 387 * This function returns fraction data value. 388 * 389 * @return Returns status, either success or error+reason 390 */ 391 static enum pm_ret_status pm_ioctl_get_pll_frac_data 392 (unsigned int pll, unsigned int *data) 393 { 394 enum pm_node_id pll_nid; 395 enum pm_ret_status status; 396 397 /* Get PLL node ID using PLL clock ID */ 398 status = pm_clock_get_pll_node_id(pll, &pll_nid); 399 if (status != PM_RET_SUCCESS) 400 return status; 401 402 return pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data); 403 } 404 405 /** 406 * pm_ioctl_write_ggs() - Ioctl function for writing 407 * global general storage (ggs) 408 * @index GGS register index 409 * @value Register value to be written 410 * 411 * This function writes value to GGS register. 412 * 413 * @return Returns status, either success or error+reason 414 */ 415 static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index, 416 unsigned int value) 417 { 418 if (index >= GGS_NUM_REGS) 419 return PM_RET_ERROR_ARGS; 420 421 return pm_mmio_write(GGS_BASEADDR + (index << 2), 422 0xFFFFFFFFU, value); 423 } 424 425 /** 426 * pm_ioctl_read_ggs() - Ioctl function for reading 427 * global general storage (ggs) 428 * @index GGS register index 429 * @value Register value 430 * 431 * This function returns GGS register value. 432 * 433 * @return Returns status, either success or error+reason 434 */ 435 static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index, 436 unsigned int *value) 437 { 438 if (index >= GGS_NUM_REGS) 439 return PM_RET_ERROR_ARGS; 440 441 return pm_mmio_read(GGS_BASEADDR + (index << 2), value); 442 } 443 444 /** 445 * pm_ioctl_write_pggs() - Ioctl function for writing persistent 446 * global general storage (pggs) 447 * @index PGGS register index 448 * @value Register value to be written 449 * 450 * This function writes value to PGGS register. 451 * 452 * @return Returns status, either success or error+reason 453 */ 454 static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index, 455 unsigned int value) 456 { 457 if (index >= PGGS_NUM_REGS) 458 return PM_RET_ERROR_ARGS; 459 460 return pm_mmio_write(PGGS_BASEADDR + (index << 2), 461 0xFFFFFFFFU, value); 462 } 463 464 /** 465 * pm_ioctl_afi() - Ioctl function for writing afi values 466 * 467 * @index AFI register index 468 * @value Register value to be written 469 * 470 * 471 * @return Returns status, either success or error+reason 472 */ 473 static enum pm_ret_status pm_ioctl_afi(unsigned int index, 474 unsigned int value) 475 { 476 unsigned int mask; 477 unsigned int regarr[] = {0xFD360000, 478 0xFD360014, 479 0xFD370000, 480 0xFD370014, 481 0xFD380000, 482 0xFD380014, 483 0xFD390000, 484 0xFD390014, 485 0xFD3a0000, 486 0xFD3a0014, 487 0xFD3b0000, 488 0xFD3b0014, 489 0xFF9b0000, 490 0xFF9b0014, 491 0xFD615000, 492 0xFF419000, 493 }; 494 495 if (index >= ARRAY_SIZE(regarr)) 496 return PM_RET_ERROR_ARGS; 497 498 if (index < AFIFM6_WRCTRL) 499 mask = FABRIC_WIDTH; 500 else 501 mask = 0xf00; 502 503 return pm_mmio_write(regarr[index], mask, value); 504 } 505 506 /** 507 * pm_ioctl_read_pggs() - Ioctl function for reading persistent 508 * global general storage (pggs) 509 * @index PGGS register index 510 * @value Register value 511 * 512 * This function returns PGGS register value. 513 * 514 * @return Returns status, either success or error+reason 515 */ 516 static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index, 517 unsigned int *value) 518 { 519 if (index >= PGGS_NUM_REGS) 520 return PM_RET_ERROR_ARGS; 521 522 return pm_mmio_read(PGGS_BASEADDR + (index << 2), value); 523 } 524 525 /** 526 * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset 527 * 528 * This function peerforms the ULPI reset sequence for resetting 529 * the ULPI transceiver. 530 * 531 * @return Returns status, either success or error+reason 532 */ 533 static enum pm_ret_status pm_ioctl_ulpi_reset(void) 534 { 535 enum pm_ret_status ret; 536 537 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 538 ZYNQMP_ULPI_RESET_VAL_HIGH); 539 if (ret != PM_RET_SUCCESS) 540 return ret; 541 542 /* Drive ULPI assert for atleast 1ms */ 543 mdelay(1); 544 545 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 546 ZYNQMP_ULPI_RESET_VAL_LOW); 547 if (ret != PM_RET_SUCCESS) 548 return ret; 549 550 /* Drive ULPI de-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_HIGH); 555 556 return ret; 557 } 558 559 /** 560 * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status 561 * 562 * This function sets healthy bit value to indicate boot health status 563 * to firmware. 564 * 565 * @return Returns status, either success or error+reason 566 */ 567 static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value) 568 { 569 return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG, 570 PM_BOOT_HEALTH_STATUS_MASK, value); 571 } 572 573 /** 574 * pm_api_ioctl() - PM IOCTL API for device control and configs 575 * @node_id Node ID of the device 576 * @ioctl_id ID of the requested IOCTL 577 * @arg1 Argument 1 to requested IOCTL call 578 * @arg2 Argument 2 to requested IOCTL call 579 * @value Returned output value 580 * 581 * This function calls IOCTL to firmware for device control and configuration. 582 * 583 * @return Returns status, either success or error+reason 584 */ 585 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, 586 unsigned int ioctl_id, 587 unsigned int arg1, 588 unsigned int arg2, 589 unsigned int *value) 590 { 591 enum pm_ret_status ret; 592 593 switch (ioctl_id) { 594 case IOCTL_GET_RPU_OPER_MODE: 595 ret = pm_ioctl_get_rpu_oper_mode(value); 596 break; 597 case IOCTL_SET_RPU_OPER_MODE: 598 ret = pm_ioctl_set_rpu_oper_mode(arg1); 599 break; 600 case IOCTL_RPU_BOOT_ADDR_CONFIG: 601 ret = pm_ioctl_config_boot_addr(nid, arg1); 602 break; 603 case IOCTL_TCM_COMB_CONFIG: 604 ret = pm_ioctl_config_tcm_comb(arg1); 605 break; 606 case IOCTL_SET_TAPDELAY_BYPASS: 607 ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2); 608 break; 609 case IOCTL_SET_SGMII_MODE: 610 ret = pm_ioctl_set_sgmii_mode(nid, arg1); 611 break; 612 case IOCTL_SD_DLL_RESET: 613 ret = pm_ioctl_sd_dll_reset(nid, arg1); 614 break; 615 case IOCTL_SET_SD_TAPDELAY: 616 ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2); 617 break; 618 case IOCTL_SET_PLL_FRAC_MODE: 619 ret = pm_ioctl_set_pll_frac_mode(arg1, arg2); 620 break; 621 case IOCTL_GET_PLL_FRAC_MODE: 622 ret = pm_ioctl_get_pll_frac_mode(arg1, value); 623 break; 624 case IOCTL_SET_PLL_FRAC_DATA: 625 ret = pm_ioctl_set_pll_frac_data(arg1, arg2); 626 break; 627 case IOCTL_GET_PLL_FRAC_DATA: 628 ret = pm_ioctl_get_pll_frac_data(arg1, value); 629 break; 630 case IOCTL_WRITE_GGS: 631 ret = pm_ioctl_write_ggs(arg1, arg2); 632 break; 633 case IOCTL_READ_GGS: 634 ret = pm_ioctl_read_ggs(arg1, value); 635 break; 636 case IOCTL_WRITE_PGGS: 637 ret = pm_ioctl_write_pggs(arg1, arg2); 638 break; 639 case IOCTL_READ_PGGS: 640 ret = pm_ioctl_read_pggs(arg1, value); 641 break; 642 case IOCTL_ULPI_RESET: 643 ret = pm_ioctl_ulpi_reset(); 644 break; 645 case IOCTL_SET_BOOT_HEALTH_STATUS: 646 ret = pm_ioctl_set_boot_health_status(arg1); 647 break; 648 case IOCTL_AFI: 649 ret = pm_ioctl_afi(arg1, arg2); 650 break; 651 default: 652 ret = PM_RET_ERROR_NOTSUPPORTED; 653 break; 654 } 655 656 return ret; 657 } 658