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