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