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