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 <drivers/delay_timer.h> 13 #include <lib/mmio.h> 14 #include <plat/common/platform.h> 15 16 #include "pm_api_clock.h" 17 #include "pm_api_ioctl.h" 18 #include "pm_api_sys.h" 19 #include "pm_client.h" 20 #include "pm_common.h" 21 #include "pm_ipi.h" 22 #include "../zynqmp_def.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 286 if (nid == NODE_SD_0) 287 shift = 0; 288 else if (nid == NODE_SD_1) 289 shift = ZYNQMP_SD_TAP_OFFSET; 290 else 291 return PM_RET_ERROR_ARGS; 292 293 ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT); 294 if (ret != PM_RET_SUCCESS) 295 return ret; 296 297 if (type == PM_TAPDELAY_INPUT) { 298 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 299 (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 300 (ZYNQMP_SD_ITAPCHGWIN << shift)); 301 if (ret != PM_RET_SUCCESS) 302 goto reset_release; 303 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 304 (ZYNQMP_SD_ITAPDLYENA_MASK << shift), 305 (ZYNQMP_SD_ITAPDLYENA << shift)); 306 if (ret != PM_RET_SUCCESS) 307 goto reset_release; 308 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 309 (ZYNQMP_SD_ITAPDLYSEL_MASK << shift), 310 (value << shift)); 311 if (ret != PM_RET_SUCCESS) 312 goto reset_release; 313 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, 314 (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0); 315 } else if (type == PM_TAPDELAY_OUTPUT) { 316 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, 317 (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 318 (ZYNQMP_SD_OTAPDLYENA << shift)); 319 if (ret != PM_RET_SUCCESS) 320 goto reset_release; 321 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, 322 (ZYNQMP_SD_OTAPDLYSEL_MASK << shift), 323 (value << shift)); 324 } else { 325 ret = PM_RET_ERROR_ARGS; 326 } 327 328 reset_release: 329 pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE); 330 return ret; 331 } 332 333 /** 334 * pm_ioctl_set_pll_frac_mode() - Ioctl function for 335 * setting pll mode 336 * @pll PLL id 337 * @mode Mode fraction/integar 338 * 339 * This function sets PLL mode 340 * 341 * @return Returns status, either success or error+reason 342 */ 343 static enum pm_ret_status pm_ioctl_set_pll_frac_mode 344 (unsigned int pll, unsigned int mode) 345 { 346 return pm_api_clk_set_pll_mode(pll, mode); 347 } 348 349 /** 350 * pm_ioctl_get_pll_frac_mode() - Ioctl function for 351 * getting pll mode 352 * @pll PLL id 353 * @mode Mode fraction/integar 354 * 355 * This function return current PLL mode 356 * 357 * @return Returns status, either success or error+reason 358 */ 359 static enum pm_ret_status pm_ioctl_get_pll_frac_mode 360 (unsigned int pll, unsigned int *mode) 361 { 362 return pm_api_clk_get_pll_mode(pll, mode); 363 } 364 365 /** 366 * pm_ioctl_set_pll_frac_data() - Ioctl function for 367 * setting pll fraction data 368 * @pll PLL id 369 * @data fraction data 370 * 371 * This function sets fraction data. 372 * It is valid for fraction mode only. 373 * 374 * @return Returns status, either success or error+reason 375 */ 376 static enum pm_ret_status pm_ioctl_set_pll_frac_data 377 (unsigned int pll, unsigned int data) 378 { 379 return pm_api_clk_set_pll_frac_data(pll, data); 380 } 381 382 /** 383 * pm_ioctl_get_pll_frac_data() - Ioctl function for 384 * getting pll fraction data 385 * @pll PLL id 386 * @data fraction data 387 * 388 * This function returns fraction data value. 389 * 390 * @return Returns status, either success or error+reason 391 */ 392 static enum pm_ret_status pm_ioctl_get_pll_frac_data 393 (unsigned int pll, unsigned int *data) 394 { 395 return pm_api_clk_get_pll_frac_data(pll, data); 396 } 397 398 /** 399 * pm_ioctl_write_ggs() - Ioctl function for writing 400 * global general storage (ggs) 401 * @index GGS register index 402 * @value Register value to be written 403 * 404 * This function writes value to GGS register. 405 * 406 * @return Returns status, either success or error+reason 407 */ 408 static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index, 409 unsigned int value) 410 { 411 if (index >= GGS_NUM_REGS) 412 return PM_RET_ERROR_ARGS; 413 414 return pm_mmio_write(GGS_BASEADDR + (index << 2), 415 0xFFFFFFFFU, value); 416 } 417 418 /** 419 * pm_ioctl_read_ggs() - Ioctl function for reading 420 * global general storage (ggs) 421 * @index GGS register index 422 * @value Register value 423 * 424 * This function returns GGS register value. 425 * 426 * @return Returns status, either success or error+reason 427 */ 428 static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index, 429 unsigned int *value) 430 { 431 if (index >= GGS_NUM_REGS) 432 return PM_RET_ERROR_ARGS; 433 434 return pm_mmio_read(GGS_BASEADDR + (index << 2), value); 435 } 436 437 /** 438 * pm_ioctl_write_pggs() - Ioctl function for writing persistent 439 * global general storage (pggs) 440 * @index PGGS register index 441 * @value Register value to be written 442 * 443 * This function writes value to PGGS register. 444 * 445 * @return Returns status, either success or error+reason 446 */ 447 static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index, 448 unsigned int value) 449 { 450 if (index >= PGGS_NUM_REGS) 451 return PM_RET_ERROR_ARGS; 452 453 return pm_mmio_write(PGGS_BASEADDR + (index << 2), 454 0xFFFFFFFFU, value); 455 } 456 457 /** 458 * pm_ioctl_afi() - Ioctl function for writing afi values 459 * 460 * @index AFI register index 461 * @value Register value to be written 462 * 463 * 464 * @return Returns status, either success or error+reason 465 */ 466 static enum pm_ret_status pm_ioctl_afi(unsigned int index, 467 unsigned int value) 468 { 469 unsigned int mask; 470 unsigned int regarr[] = {0xFD360000, 471 0xFD360014, 472 0xFD370000, 473 0xFD370014, 474 0xFD380000, 475 0xFD380014, 476 0xFD390000, 477 0xFD390014, 478 0xFD3a0000, 479 0xFD3a0014, 480 0xFD3b0000, 481 0xFD3b0014, 482 0xFF9b0000, 483 0xFF9b0014, 484 0xFD615000, 485 0xFF419000, 486 }; 487 488 if (index >= ARRAY_SIZE(regarr)) 489 return PM_RET_ERROR_ARGS; 490 491 if (index < AFIFM6_WRCTRL) 492 mask = FABRIC_WIDTH; 493 else 494 mask = 0xf00; 495 496 return pm_mmio_write(regarr[index], mask, value); 497 } 498 499 /** 500 * pm_ioctl_read_pggs() - Ioctl function for reading persistent 501 * global general storage (pggs) 502 * @index PGGS register index 503 * @value Register value 504 * 505 * This function returns PGGS register value. 506 * 507 * @return Returns status, either success or error+reason 508 */ 509 static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index, 510 unsigned int *value) 511 { 512 if (index >= PGGS_NUM_REGS) 513 return PM_RET_ERROR_ARGS; 514 515 return pm_mmio_read(PGGS_BASEADDR + (index << 2), value); 516 } 517 518 /** 519 * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset 520 * 521 * This function peerforms the ULPI reset sequence for resetting 522 * the ULPI transceiver. 523 * 524 * @return Returns status, either success or error+reason 525 */ 526 static enum pm_ret_status pm_ioctl_ulpi_reset(void) 527 { 528 enum pm_ret_status ret; 529 530 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 531 ZYNQMP_ULPI_RESET_VAL_HIGH); 532 if (ret != PM_RET_SUCCESS) 533 return ret; 534 535 /* Drive ULPI assert for atleast 1ms */ 536 mdelay(1); 537 538 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 539 ZYNQMP_ULPI_RESET_VAL_LOW); 540 if (ret != PM_RET_SUCCESS) 541 return ret; 542 543 /* Drive ULPI de-assert for atleast 1ms */ 544 mdelay(1); 545 546 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, 547 ZYNQMP_ULPI_RESET_VAL_HIGH); 548 549 return ret; 550 } 551 552 /** 553 * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status 554 * 555 * This function sets healthy bit value to indicate boot health status 556 * to firmware. 557 * 558 * @return Returns status, either success or error+reason 559 */ 560 static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value) 561 { 562 return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG, 563 PM_BOOT_HEALTH_STATUS_MASK, value); 564 } 565 566 /** 567 * pm_api_ioctl() - PM IOCTL API for device control and configs 568 * @node_id Node ID of the device 569 * @ioctl_id ID of the requested IOCTL 570 * @arg1 Argument 1 to requested IOCTL call 571 * @arg2 Argument 2 to requested IOCTL call 572 * @value Returned output value 573 * 574 * This function calls IOCTL to firmware for device control and configuration. 575 * 576 * @return Returns status, either success or error+reason 577 */ 578 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, 579 unsigned int ioctl_id, 580 unsigned int arg1, 581 unsigned int arg2, 582 unsigned int *value) 583 { 584 enum pm_ret_status ret; 585 586 switch (ioctl_id) { 587 case IOCTL_GET_RPU_OPER_MODE: 588 ret = pm_ioctl_get_rpu_oper_mode(value); 589 break; 590 case IOCTL_SET_RPU_OPER_MODE: 591 ret = pm_ioctl_set_rpu_oper_mode(arg1); 592 break; 593 case IOCTL_RPU_BOOT_ADDR_CONFIG: 594 ret = pm_ioctl_config_boot_addr(nid, arg1); 595 break; 596 case IOCTL_TCM_COMB_CONFIG: 597 ret = pm_ioctl_config_tcm_comb(arg1); 598 break; 599 case IOCTL_SET_TAPDELAY_BYPASS: 600 ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2); 601 break; 602 case IOCTL_SET_SGMII_MODE: 603 ret = pm_ioctl_set_sgmii_mode(nid, arg1); 604 break; 605 case IOCTL_SD_DLL_RESET: 606 ret = pm_ioctl_sd_dll_reset(nid, arg1); 607 break; 608 case IOCTL_SET_SD_TAPDELAY: 609 ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2); 610 break; 611 case IOCTL_SET_PLL_FRAC_MODE: 612 ret = pm_ioctl_set_pll_frac_mode(arg1, arg2); 613 break; 614 case IOCTL_GET_PLL_FRAC_MODE: 615 ret = pm_ioctl_get_pll_frac_mode(arg1, value); 616 break; 617 case IOCTL_SET_PLL_FRAC_DATA: 618 ret = pm_ioctl_set_pll_frac_data(arg1, arg2); 619 break; 620 case IOCTL_GET_PLL_FRAC_DATA: 621 ret = pm_ioctl_get_pll_frac_data(arg1, value); 622 break; 623 case IOCTL_WRITE_GGS: 624 ret = pm_ioctl_write_ggs(arg1, arg2); 625 break; 626 case IOCTL_READ_GGS: 627 ret = pm_ioctl_read_ggs(arg1, value); 628 break; 629 case IOCTL_WRITE_PGGS: 630 ret = pm_ioctl_write_pggs(arg1, arg2); 631 break; 632 case IOCTL_READ_PGGS: 633 ret = pm_ioctl_read_pggs(arg1, value); 634 break; 635 case IOCTL_ULPI_RESET: 636 ret = pm_ioctl_ulpi_reset(); 637 break; 638 case IOCTL_SET_BOOT_HEALTH_STATUS: 639 ret = pm_ioctl_set_boot_health_status(arg1); 640 break; 641 case IOCTL_AFI: 642 ret = pm_ioctl_afi(arg1, arg2); 643 break; 644 default: 645 ret = PM_RET_ERROR_NOTSUPPORTED; 646 break; 647 } 648 649 return ret; 650 } 651