1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2013-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 and communication with PMU via 10*91f16700Schasinglulu * IPI interrupts 11*91f16700Schasinglulu */ 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <plat/common/platform.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include "pm_api_clock.h" 17*91f16700Schasinglulu #include "pm_api_ioctl.h" 18*91f16700Schasinglulu #include "pm_api_pinctrl.h" 19*91f16700Schasinglulu #include "pm_client.h" 20*91f16700Schasinglulu #include "pm_common.h" 21*91f16700Schasinglulu #include "pm_ipi.h" 22*91f16700Schasinglulu #include "zynqmp_pm_api_sys.h" 23*91f16700Schasinglulu 24*91f16700Schasinglulu #define PM_QUERY_FEATURE_BITMASK ( \ 25*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \ 26*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \ 27*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \ 28*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \ 29*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \ 30*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \ 31*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \ 32*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \ 33*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \ 34*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \ 35*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \ 36*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \ 37*91f16700Schasinglulu (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR)) 38*91f16700Schasinglulu 39*91f16700Schasinglulu /** 40*91f16700Schasinglulu * typedef eemi_api_dependency - Dependent EEMI APIs which are implemented 41*91f16700Schasinglulu * on both the TF-A and firmware. 42*91f16700Schasinglulu * @id: EEMI API id or IOCTL id to be checked. 43*91f16700Schasinglulu * @api_id: Dependent EEMI API. 44*91f16700Schasinglulu * 45*91f16700Schasinglulu */ 46*91f16700Schasinglulu typedef struct __attribute__((packed)) { 47*91f16700Schasinglulu uint8_t id; 48*91f16700Schasinglulu uint8_t api_id; 49*91f16700Schasinglulu } eemi_api_dependency; 50*91f16700Schasinglulu 51*91f16700Schasinglulu /* Dependent APIs for TF-A to check their version from firmware */ 52*91f16700Schasinglulu static const eemi_api_dependency api_dep_table[] = { 53*91f16700Schasinglulu { 54*91f16700Schasinglulu .id = PM_SELF_SUSPEND, 55*91f16700Schasinglulu .api_id = PM_SELF_SUSPEND, 56*91f16700Schasinglulu }, 57*91f16700Schasinglulu { 58*91f16700Schasinglulu .id = PM_REQ_WAKEUP, 59*91f16700Schasinglulu .api_id = PM_REQ_WAKEUP, 60*91f16700Schasinglulu }, 61*91f16700Schasinglulu { 62*91f16700Schasinglulu .id = PM_ABORT_SUSPEND, 63*91f16700Schasinglulu .api_id = PM_ABORT_SUSPEND, 64*91f16700Schasinglulu }, 65*91f16700Schasinglulu { 66*91f16700Schasinglulu .id = PM_SET_WAKEUP_SOURCE, 67*91f16700Schasinglulu .api_id = PM_SET_WAKEUP_SOURCE, 68*91f16700Schasinglulu }, 69*91f16700Schasinglulu { 70*91f16700Schasinglulu .id = PM_SYSTEM_SHUTDOWN, 71*91f16700Schasinglulu .api_id = PM_SYSTEM_SHUTDOWN, 72*91f16700Schasinglulu }, 73*91f16700Schasinglulu { 74*91f16700Schasinglulu .id = PM_GET_API_VERSION, 75*91f16700Schasinglulu .api_id = PM_GET_API_VERSION, 76*91f16700Schasinglulu }, 77*91f16700Schasinglulu { 78*91f16700Schasinglulu .id = PM_CLOCK_ENABLE, 79*91f16700Schasinglulu .api_id = PM_PLL_SET_MODE, 80*91f16700Schasinglulu }, 81*91f16700Schasinglulu { 82*91f16700Schasinglulu .id = PM_CLOCK_ENABLE, 83*91f16700Schasinglulu .api_id = PM_CLOCK_ENABLE, 84*91f16700Schasinglulu }, 85*91f16700Schasinglulu { 86*91f16700Schasinglulu .id = PM_CLOCK_DISABLE, 87*91f16700Schasinglulu .api_id = PM_PLL_SET_MODE, 88*91f16700Schasinglulu }, 89*91f16700Schasinglulu { 90*91f16700Schasinglulu .id = PM_CLOCK_DISABLE, 91*91f16700Schasinglulu .api_id = PM_CLOCK_DISABLE, 92*91f16700Schasinglulu }, 93*91f16700Schasinglulu { 94*91f16700Schasinglulu .id = PM_CLOCK_GETSTATE, 95*91f16700Schasinglulu .api_id = PM_PLL_GET_MODE, 96*91f16700Schasinglulu }, 97*91f16700Schasinglulu { 98*91f16700Schasinglulu .id = PM_CLOCK_GETSTATE, 99*91f16700Schasinglulu .api_id = PM_CLOCK_GETSTATE, 100*91f16700Schasinglulu }, 101*91f16700Schasinglulu { 102*91f16700Schasinglulu .id = PM_CLOCK_SETDIVIDER, 103*91f16700Schasinglulu .api_id = PM_PLL_SET_PARAMETER, 104*91f16700Schasinglulu }, 105*91f16700Schasinglulu { 106*91f16700Schasinglulu .id = PM_CLOCK_SETDIVIDER, 107*91f16700Schasinglulu .api_id = PM_CLOCK_SETDIVIDER, 108*91f16700Schasinglulu }, 109*91f16700Schasinglulu { 110*91f16700Schasinglulu .id = PM_CLOCK_GETDIVIDER, 111*91f16700Schasinglulu .api_id = PM_PLL_GET_PARAMETER, 112*91f16700Schasinglulu }, 113*91f16700Schasinglulu { 114*91f16700Schasinglulu .id = PM_CLOCK_GETDIVIDER, 115*91f16700Schasinglulu .api_id = PM_CLOCK_GETDIVIDER, 116*91f16700Schasinglulu }, 117*91f16700Schasinglulu { 118*91f16700Schasinglulu .id = PM_CLOCK_SETPARENT, 119*91f16700Schasinglulu .api_id = PM_PLL_SET_PARAMETER, 120*91f16700Schasinglulu }, 121*91f16700Schasinglulu { 122*91f16700Schasinglulu .id = PM_CLOCK_SETPARENT, 123*91f16700Schasinglulu .api_id = PM_CLOCK_SETPARENT, 124*91f16700Schasinglulu }, 125*91f16700Schasinglulu { 126*91f16700Schasinglulu .id = PM_CLOCK_GETPARENT, 127*91f16700Schasinglulu .api_id = PM_PLL_GET_PARAMETER, 128*91f16700Schasinglulu }, 129*91f16700Schasinglulu { 130*91f16700Schasinglulu .id = PM_CLOCK_GETPARENT, 131*91f16700Schasinglulu .api_id = PM_CLOCK_GETPARENT, 132*91f16700Schasinglulu }, 133*91f16700Schasinglulu { 134*91f16700Schasinglulu .id = PM_PLL_SET_PARAMETER, 135*91f16700Schasinglulu .api_id = PM_PLL_SET_PARAMETER, 136*91f16700Schasinglulu }, 137*91f16700Schasinglulu { 138*91f16700Schasinglulu .id = PM_PLL_GET_PARAMETER, 139*91f16700Schasinglulu .api_id = PM_PLL_GET_PARAMETER, 140*91f16700Schasinglulu }, 141*91f16700Schasinglulu { 142*91f16700Schasinglulu .id = PM_PLL_SET_MODE, 143*91f16700Schasinglulu .api_id = PM_PLL_SET_MODE, 144*91f16700Schasinglulu }, 145*91f16700Schasinglulu { 146*91f16700Schasinglulu .id = PM_PLL_GET_MODE, 147*91f16700Schasinglulu .api_id = PM_PLL_GET_MODE, 148*91f16700Schasinglulu }, 149*91f16700Schasinglulu { 150*91f16700Schasinglulu .id = PM_REGISTER_ACCESS, 151*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 152*91f16700Schasinglulu }, 153*91f16700Schasinglulu { 154*91f16700Schasinglulu .id = PM_REGISTER_ACCESS, 155*91f16700Schasinglulu .api_id = PM_MMIO_READ, 156*91f16700Schasinglulu }, 157*91f16700Schasinglulu { 158*91f16700Schasinglulu .id = PM_FEATURE_CHECK, 159*91f16700Schasinglulu .api_id = PM_FEATURE_CHECK, 160*91f16700Schasinglulu }, 161*91f16700Schasinglulu { 162*91f16700Schasinglulu .id = IOCTL_SET_TAPDELAY_BYPASS, 163*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 164*91f16700Schasinglulu }, 165*91f16700Schasinglulu { 166*91f16700Schasinglulu .id = IOCTL_SD_DLL_RESET, 167*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 168*91f16700Schasinglulu }, 169*91f16700Schasinglulu { 170*91f16700Schasinglulu .id = IOCTL_SET_SD_TAPDELAY, 171*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 172*91f16700Schasinglulu }, 173*91f16700Schasinglulu { 174*91f16700Schasinglulu .id = IOCTL_SET_SD_TAPDELAY, 175*91f16700Schasinglulu .api_id = PM_MMIO_READ, 176*91f16700Schasinglulu }, 177*91f16700Schasinglulu { 178*91f16700Schasinglulu .id = IOCTL_SET_PLL_FRAC_DATA, 179*91f16700Schasinglulu .api_id = PM_PLL_SET_PARAMETER, 180*91f16700Schasinglulu }, 181*91f16700Schasinglulu { 182*91f16700Schasinglulu .id = IOCTL_GET_PLL_FRAC_DATA, 183*91f16700Schasinglulu .api_id = PM_PLL_GET_PARAMETER, 184*91f16700Schasinglulu }, 185*91f16700Schasinglulu { 186*91f16700Schasinglulu .id = IOCTL_WRITE_GGS, 187*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 188*91f16700Schasinglulu }, 189*91f16700Schasinglulu { 190*91f16700Schasinglulu .id = IOCTL_READ_GGS, 191*91f16700Schasinglulu .api_id = PM_MMIO_READ, 192*91f16700Schasinglulu }, 193*91f16700Schasinglulu { 194*91f16700Schasinglulu .id = IOCTL_WRITE_PGGS, 195*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 196*91f16700Schasinglulu }, 197*91f16700Schasinglulu { 198*91f16700Schasinglulu .id = IOCTL_READ_PGGS, 199*91f16700Schasinglulu .api_id = PM_MMIO_READ, 200*91f16700Schasinglulu }, 201*91f16700Schasinglulu { 202*91f16700Schasinglulu .id = IOCTL_ULPI_RESET, 203*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 204*91f16700Schasinglulu }, 205*91f16700Schasinglulu { 206*91f16700Schasinglulu .id = IOCTL_SET_BOOT_HEALTH_STATUS, 207*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 208*91f16700Schasinglulu }, 209*91f16700Schasinglulu { 210*91f16700Schasinglulu .id = IOCTL_AFI, 211*91f16700Schasinglulu .api_id = PM_MMIO_WRITE, 212*91f16700Schasinglulu }, 213*91f16700Schasinglulu }; 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* Expected firmware API version to TF-A */ 216*91f16700Schasinglulu static const uint8_t tfa_expected_ver_id[] = { 217*91f16700Schasinglulu [PM_SELF_SUSPEND] = FW_API_BASE_VERSION, 218*91f16700Schasinglulu [PM_REQ_WAKEUP] = FW_API_BASE_VERSION, 219*91f16700Schasinglulu [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION, 220*91f16700Schasinglulu [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION, 221*91f16700Schasinglulu [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION, 222*91f16700Schasinglulu [PM_GET_API_VERSION] = FW_API_BASE_VERSION, 223*91f16700Schasinglulu [PM_PLL_SET_MODE] = FW_API_BASE_VERSION, 224*91f16700Schasinglulu [PM_PLL_GET_MODE] = FW_API_BASE_VERSION, 225*91f16700Schasinglulu [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION, 226*91f16700Schasinglulu [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION, 227*91f16700Schasinglulu [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION, 228*91f16700Schasinglulu [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION, 229*91f16700Schasinglulu [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION, 230*91f16700Schasinglulu [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION, 231*91f16700Schasinglulu [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION, 232*91f16700Schasinglulu [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION, 233*91f16700Schasinglulu [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION, 234*91f16700Schasinglulu [PM_MMIO_WRITE] = FW_API_BASE_VERSION, 235*91f16700Schasinglulu [PM_MMIO_READ] = FW_API_BASE_VERSION, 236*91f16700Schasinglulu [PM_FEATURE_CHECK] = FW_API_VERSION_2, 237*91f16700Schasinglulu }; 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* default shutdown/reboot scope is system(2) */ 240*91f16700Schasinglulu static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM; 241*91f16700Schasinglulu 242*91f16700Schasinglulu /** 243*91f16700Schasinglulu * pm_get_shutdown_scope() - Get the currently set shutdown scope. 244*91f16700Schasinglulu * 245*91f16700Schasinglulu * Return: Shutdown scope value. 246*91f16700Schasinglulu * 247*91f16700Schasinglulu */ 248*91f16700Schasinglulu uint32_t pm_get_shutdown_scope(void) 249*91f16700Schasinglulu { 250*91f16700Schasinglulu return pm_shutdown_scope; 251*91f16700Schasinglulu } 252*91f16700Schasinglulu 253*91f16700Schasinglulu /** 254*91f16700Schasinglulu * pm_self_suspend() - PM call for processor to suspend itself. 255*91f16700Schasinglulu * @nid: Node id of the processor or subsystem. 256*91f16700Schasinglulu * @latency: Requested maximum wakeup latency (not supported). 257*91f16700Schasinglulu * @state: Requested state. 258*91f16700Schasinglulu * @address: Resume address. 259*91f16700Schasinglulu * 260*91f16700Schasinglulu * This is a blocking call, it will return only once PMU has responded. 261*91f16700Schasinglulu * On a wakeup, resume address will be automatically set by PMU. 262*91f16700Schasinglulu * 263*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 264*91f16700Schasinglulu * 265*91f16700Schasinglulu */ 266*91f16700Schasinglulu enum pm_ret_status pm_self_suspend(enum pm_node_id nid, 267*91f16700Schasinglulu uint32_t latency, 268*91f16700Schasinglulu uint32_t state, 269*91f16700Schasinglulu uintptr_t address) 270*91f16700Schasinglulu { 271*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 272*91f16700Schasinglulu uint32_t cpuid = plat_my_core_pos(); 273*91f16700Schasinglulu const struct pm_proc *proc = pm_get_proc(cpuid); 274*91f16700Schasinglulu 275*91f16700Schasinglulu /* 276*91f16700Schasinglulu * Do client specific suspend operations 277*91f16700Schasinglulu * (e.g. set powerdown request bit) 278*91f16700Schasinglulu */ 279*91f16700Schasinglulu pm_client_suspend(proc, state); 280*91f16700Schasinglulu /* Send request to the PMU */ 281*91f16700Schasinglulu PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, 282*91f16700Schasinglulu state, address, (address >> 32)); 283*91f16700Schasinglulu return pm_ipi_send_sync(proc, payload, NULL, 0); 284*91f16700Schasinglulu } 285*91f16700Schasinglulu 286*91f16700Schasinglulu /** 287*91f16700Schasinglulu * pm_req_suspend() - PM call to request for another PU or subsystem to 288*91f16700Schasinglulu * be suspended gracefully. 289*91f16700Schasinglulu * @target: Node id of the targeted PU or subsystem. 290*91f16700Schasinglulu * @ack: Flag to specify whether acknowledge is requested. 291*91f16700Schasinglulu * @latency: Requested wakeup latency (not supported). 292*91f16700Schasinglulu * @state: Requested state (not supported). 293*91f16700Schasinglulu * 294*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 295*91f16700Schasinglulu * 296*91f16700Schasinglulu */ 297*91f16700Schasinglulu enum pm_ret_status pm_req_suspend(enum pm_node_id target, 298*91f16700Schasinglulu enum pm_request_ack ack, 299*91f16700Schasinglulu uint32_t latency, uint32_t state) 300*91f16700Schasinglulu { 301*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 302*91f16700Schasinglulu 303*91f16700Schasinglulu /* Send request to the PMU */ 304*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state); 305*91f16700Schasinglulu if (ack == REQ_ACK_BLOCKING) { 306*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 307*91f16700Schasinglulu } else { 308*91f16700Schasinglulu return pm_ipi_send(primary_proc, payload); 309*91f16700Schasinglulu } 310*91f16700Schasinglulu } 311*91f16700Schasinglulu 312*91f16700Schasinglulu /** 313*91f16700Schasinglulu * pm_req_wakeup() - PM call for processor to wake up selected processor 314*91f16700Schasinglulu * or subsystem. 315*91f16700Schasinglulu * @target: Node id of the processor or subsystem to wake up. 316*91f16700Schasinglulu * @ack: Flag to specify whether acknowledge requested. 317*91f16700Schasinglulu * @set_address: Resume address presence indicator. 318*91f16700Schasinglulu * 1 resume address specified, 0 otherwise. 319*91f16700Schasinglulu * @address: Resume address. 320*91f16700Schasinglulu * 321*91f16700Schasinglulu * This API function is either used to power up another APU core for SMP 322*91f16700Schasinglulu * (by PSCI) or to power up an entirely different PU or subsystem, such 323*91f16700Schasinglulu * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be 324*91f16700Schasinglulu * automatically set by PMU. 325*91f16700Schasinglulu * 326*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 327*91f16700Schasinglulu * 328*91f16700Schasinglulu */ 329*91f16700Schasinglulu enum pm_ret_status pm_req_wakeup(enum pm_node_id target, 330*91f16700Schasinglulu uint32_t set_address, 331*91f16700Schasinglulu uintptr_t address, 332*91f16700Schasinglulu enum pm_request_ack ack) 333*91f16700Schasinglulu { 334*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 335*91f16700Schasinglulu uint64_t encoded_address; 336*91f16700Schasinglulu 337*91f16700Schasinglulu 338*91f16700Schasinglulu /* encode set Address into 1st bit of address */ 339*91f16700Schasinglulu encoded_address = address; 340*91f16700Schasinglulu encoded_address |= !!set_address; 341*91f16700Schasinglulu 342*91f16700Schasinglulu /* Send request to the PMU to perform the wake of the PU */ 343*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address, 344*91f16700Schasinglulu encoded_address >> 32, ack); 345*91f16700Schasinglulu 346*91f16700Schasinglulu if (ack == REQ_ACK_BLOCKING) { 347*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 348*91f16700Schasinglulu } else { 349*91f16700Schasinglulu return pm_ipi_send(primary_proc, payload); 350*91f16700Schasinglulu } 351*91f16700Schasinglulu } 352*91f16700Schasinglulu 353*91f16700Schasinglulu /** 354*91f16700Schasinglulu * pm_force_powerdown() - PM call to request for another PU or subsystem to 355*91f16700Schasinglulu * be powered down forcefully. 356*91f16700Schasinglulu * @target: Node id of the targeted PU or subsystem. 357*91f16700Schasinglulu * @ack: Flag to specify whether acknowledge is requested. 358*91f16700Schasinglulu * 359*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 360*91f16700Schasinglulu * 361*91f16700Schasinglulu */ 362*91f16700Schasinglulu enum pm_ret_status pm_force_powerdown(enum pm_node_id target, 363*91f16700Schasinglulu enum pm_request_ack ack) 364*91f16700Schasinglulu { 365*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 366*91f16700Schasinglulu 367*91f16700Schasinglulu /* Send request to the PMU */ 368*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack); 369*91f16700Schasinglulu 370*91f16700Schasinglulu if (ack == REQ_ACK_BLOCKING) { 371*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 372*91f16700Schasinglulu } else { 373*91f16700Schasinglulu return pm_ipi_send(primary_proc, payload); 374*91f16700Schasinglulu } 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /** 378*91f16700Schasinglulu * pm_abort_suspend() - PM call to announce that a prior suspend request 379*91f16700Schasinglulu * is to be aborted. 380*91f16700Schasinglulu * @reason: Reason for the abort. 381*91f16700Schasinglulu * 382*91f16700Schasinglulu * Calling PU expects the PMU to abort the initiated suspend procedure. 383*91f16700Schasinglulu * This is a non-blocking call without any acknowledge. 384*91f16700Schasinglulu * 385*91f16700Schasinglulu * Return: Returns status, either success or error+reason 386*91f16700Schasinglulu * 387*91f16700Schasinglulu */ 388*91f16700Schasinglulu enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason) 389*91f16700Schasinglulu { 390*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 391*91f16700Schasinglulu 392*91f16700Schasinglulu /* 393*91f16700Schasinglulu * Do client specific abort suspend operations 394*91f16700Schasinglulu * (e.g. enable interrupts and clear powerdown request bit) 395*91f16700Schasinglulu */ 396*91f16700Schasinglulu pm_client_abort_suspend(); 397*91f16700Schasinglulu /* Send request to the PMU */ 398*91f16700Schasinglulu /* TODO: allow passing the node ID of the affected CPU */ 399*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason, 400*91f16700Schasinglulu primary_proc->node_id); 401*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu /** 405*91f16700Schasinglulu * pm_set_wakeup_source() - PM call to specify the wakeup source while 406*91f16700Schasinglulu * suspended. 407*91f16700Schasinglulu * @target: Node id of the targeted PU or subsystem. 408*91f16700Schasinglulu * @wkup_node: Node id of the wakeup peripheral. 409*91f16700Schasinglulu * @enable: Enable or disable the specified peripheral as wake source. 410*91f16700Schasinglulu * 411*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 412*91f16700Schasinglulu * 413*91f16700Schasinglulu */ 414*91f16700Schasinglulu enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target, 415*91f16700Schasinglulu enum pm_node_id wkup_node, 416*91f16700Schasinglulu uint32_t enable) 417*91f16700Schasinglulu { 418*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 419*91f16700Schasinglulu 420*91f16700Schasinglulu PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node, 421*91f16700Schasinglulu enable); 422*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 423*91f16700Schasinglulu } 424*91f16700Schasinglulu 425*91f16700Schasinglulu /** 426*91f16700Schasinglulu * pm_system_shutdown() - PM call to request a system shutdown or restart. 427*91f16700Schasinglulu * @type: Shutdown or restart? 0=shutdown, 1=restart, 2=setscope. 428*91f16700Schasinglulu * @subtype: Scope: 0=APU-subsystem, 1=PS, 2=system. 429*91f16700Schasinglulu * 430*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 431*91f16700Schasinglulu * 432*91f16700Schasinglulu */ 433*91f16700Schasinglulu enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) 434*91f16700Schasinglulu { 435*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 436*91f16700Schasinglulu 437*91f16700Schasinglulu if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) { 438*91f16700Schasinglulu /* Setting scope for subsequent PSCI reboot or shutdown */ 439*91f16700Schasinglulu pm_shutdown_scope = subtype; 440*91f16700Schasinglulu return PM_RET_SUCCESS; 441*91f16700Schasinglulu } 442*91f16700Schasinglulu 443*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype); 444*91f16700Schasinglulu return pm_ipi_send_non_blocking(primary_proc, payload); 445*91f16700Schasinglulu } 446*91f16700Schasinglulu 447*91f16700Schasinglulu /* APIs for managing PM slaves: */ 448*91f16700Schasinglulu 449*91f16700Schasinglulu /** 450*91f16700Schasinglulu * pm_req_node() - PM call to request a node with specific capabilities. 451*91f16700Schasinglulu * @nid: Node id of the slave. 452*91f16700Schasinglulu * @capabilities: Requested capabilities of the slave. 453*91f16700Schasinglulu * @qos: Quality of service (not supported). 454*91f16700Schasinglulu * @ack: Flag to specify whether acknowledge is requested. 455*91f16700Schasinglulu * 456*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 457*91f16700Schasinglulu * 458*91f16700Schasinglulu */ 459*91f16700Schasinglulu enum pm_ret_status pm_req_node(enum pm_node_id nid, 460*91f16700Schasinglulu uint32_t capabilities, 461*91f16700Schasinglulu uint32_t qos, 462*91f16700Schasinglulu enum pm_request_ack ack) 463*91f16700Schasinglulu { 464*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 465*91f16700Schasinglulu 466*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack); 467*91f16700Schasinglulu 468*91f16700Schasinglulu if (ack == REQ_ACK_BLOCKING) { 469*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 470*91f16700Schasinglulu } else { 471*91f16700Schasinglulu return pm_ipi_send(primary_proc, payload); 472*91f16700Schasinglulu } 473*91f16700Schasinglulu } 474*91f16700Schasinglulu 475*91f16700Schasinglulu /** 476*91f16700Schasinglulu * pm_set_requirement() - PM call to set requirement for PM slaves. 477*91f16700Schasinglulu * @nid: Node id of the slave. 478*91f16700Schasinglulu * @capabilities: Requested capabilities of the slave. 479*91f16700Schasinglulu * @qos: Quality of service (not supported). 480*91f16700Schasinglulu * @ack: Flag to specify whether acknowledge is requested. 481*91f16700Schasinglulu * 482*91f16700Schasinglulu * This API function is to be used for slaves a PU already has requested. 483*91f16700Schasinglulu * 484*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 485*91f16700Schasinglulu * 486*91f16700Schasinglulu */ 487*91f16700Schasinglulu enum pm_ret_status pm_set_requirement(enum pm_node_id nid, 488*91f16700Schasinglulu uint32_t capabilities, 489*91f16700Schasinglulu uint32_t qos, 490*91f16700Schasinglulu enum pm_request_ack ack) 491*91f16700Schasinglulu { 492*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 493*91f16700Schasinglulu 494*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos, 495*91f16700Schasinglulu ack); 496*91f16700Schasinglulu 497*91f16700Schasinglulu if (ack == REQ_ACK_BLOCKING) { 498*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 499*91f16700Schasinglulu } else { 500*91f16700Schasinglulu return pm_ipi_send(primary_proc, payload); 501*91f16700Schasinglulu } 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu /* Miscellaneous API functions */ 505*91f16700Schasinglulu 506*91f16700Schasinglulu /** 507*91f16700Schasinglulu * pm_get_api_version() - Get version number of PMU PM firmware. 508*91f16700Schasinglulu * @version: Returns 32-bit version number of PMU Power Management Firmware. 509*91f16700Schasinglulu * 510*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 511*91f16700Schasinglulu * 512*91f16700Schasinglulu */ 513*91f16700Schasinglulu enum pm_ret_status pm_get_api_version(uint32_t *version) 514*91f16700Schasinglulu { 515*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 516*91f16700Schasinglulu 517*91f16700Schasinglulu /* Send request to the PMU */ 518*91f16700Schasinglulu PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION); 519*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, version, 1); 520*91f16700Schasinglulu } 521*91f16700Schasinglulu 522*91f16700Schasinglulu /** 523*91f16700Schasinglulu * pm_get_node_status() - PM call to request a node's current status. 524*91f16700Schasinglulu * @nid: Node id. 525*91f16700Schasinglulu * @ret_buff: Buffer for the return values 526*91f16700Schasinglulu * [0] - Current power state of the node 527*91f16700Schasinglulu * [1] - Current requirements for the node (slave nodes only) 528*91f16700Schasinglulu * [2] - Current usage status for the node (slave nodes only) 529*91f16700Schasinglulu * 530*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 531*91f16700Schasinglulu * 532*91f16700Schasinglulu */ 533*91f16700Schasinglulu enum pm_ret_status pm_get_node_status(enum pm_node_id nid, 534*91f16700Schasinglulu uint32_t *ret_buff) 535*91f16700Schasinglulu { 536*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 537*91f16700Schasinglulu 538*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid); 539*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3); 540*91f16700Schasinglulu } 541*91f16700Schasinglulu 542*91f16700Schasinglulu /** 543*91f16700Schasinglulu * pm_mmio_write() - Perform write to protected mmio. 544*91f16700Schasinglulu * @address: Address to write to. 545*91f16700Schasinglulu * @mask: Mask to apply. 546*91f16700Schasinglulu * @value: Value to write. 547*91f16700Schasinglulu * 548*91f16700Schasinglulu * This function provides access to PM-related control registers 549*91f16700Schasinglulu * that may not be directly accessible by a particular PU. 550*91f16700Schasinglulu * 551*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 552*91f16700Schasinglulu * 553*91f16700Schasinglulu */ 554*91f16700Schasinglulu enum pm_ret_status pm_mmio_write(uintptr_t address, 555*91f16700Schasinglulu uint32_t mask, 556*91f16700Schasinglulu uint32_t value) 557*91f16700Schasinglulu { 558*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 559*91f16700Schasinglulu 560*91f16700Schasinglulu /* Send request to the PMU */ 561*91f16700Schasinglulu PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); 562*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 563*91f16700Schasinglulu } 564*91f16700Schasinglulu 565*91f16700Schasinglulu /** 566*91f16700Schasinglulu * pm_mmio_read() - Read value from protected mmio. 567*91f16700Schasinglulu * @address: Address to write to. 568*91f16700Schasinglulu * @value: Value to write. 569*91f16700Schasinglulu * 570*91f16700Schasinglulu * This function provides access to PM-related control registers 571*91f16700Schasinglulu * that may not be directly accessible by a particular PU. 572*91f16700Schasinglulu * 573*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 574*91f16700Schasinglulu * 575*91f16700Schasinglulu */ 576*91f16700Schasinglulu enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value) 577*91f16700Schasinglulu { 578*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 579*91f16700Schasinglulu 580*91f16700Schasinglulu /* Send request to the PMU */ 581*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); 582*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 583*91f16700Schasinglulu } 584*91f16700Schasinglulu 585*91f16700Schasinglulu /** 586*91f16700Schasinglulu * pm_fpga_load() - Load the bitstream into the PL. This function provides 587*91f16700Schasinglulu * access to the xilfpga library to load the Bit-stream 588*91f16700Schasinglulu * into PL. 589*91f16700Schasinglulu * @address_low: lower 32-bit Linear memory space address. 590*91f16700Schasinglulu * @address_high: higher 32-bit Linear memory space address. 591*91f16700Schasinglulu * @size: Number of 32bit words. 592*91f16700Schasinglulu * @flags: Additional flags or settings for the fpga operation. 593*91f16700Schasinglulu * 594*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 595*91f16700Schasinglulu * 596*91f16700Schasinglulu */ 597*91f16700Schasinglulu enum pm_ret_status pm_fpga_load(uint32_t address_low, 598*91f16700Schasinglulu uint32_t address_high, 599*91f16700Schasinglulu uint32_t size, 600*91f16700Schasinglulu uint32_t flags) 601*91f16700Schasinglulu { 602*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 603*91f16700Schasinglulu 604*91f16700Schasinglulu /* Send request to the PMU */ 605*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low, 606*91f16700Schasinglulu size, flags); 607*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 608*91f16700Schasinglulu } 609*91f16700Schasinglulu 610*91f16700Schasinglulu /** 611*91f16700Schasinglulu * pm_fpga_get_status() - Read value from fpga status register. 612*91f16700Schasinglulu * @value: Value to read. 613*91f16700Schasinglulu * 614*91f16700Schasinglulu * This function provides access to the xilfpga library to get 615*91f16700Schasinglulu * the fpga status. 616*91f16700Schasinglulu * 617*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 618*91f16700Schasinglulu * 619*91f16700Schasinglulu */ 620*91f16700Schasinglulu enum pm_ret_status pm_fpga_get_status(uint32_t *value) 621*91f16700Schasinglulu { 622*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 623*91f16700Schasinglulu 624*91f16700Schasinglulu /* Send request to the PMU */ 625*91f16700Schasinglulu PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS); 626*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 627*91f16700Schasinglulu } 628*91f16700Schasinglulu 629*91f16700Schasinglulu /** 630*91f16700Schasinglulu * pm_get_chipid() - Read silicon ID registers. 631*91f16700Schasinglulu * @value: Buffer for return values. Must be large enough to hold 8 bytes. 632*91f16700Schasinglulu * 633*91f16700Schasinglulu * Return: Returns silicon ID registers. 634*91f16700Schasinglulu * 635*91f16700Schasinglulu */ 636*91f16700Schasinglulu enum pm_ret_status pm_get_chipid(uint32_t *value) 637*91f16700Schasinglulu { 638*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 639*91f16700Schasinglulu 640*91f16700Schasinglulu /* Send request to the PMU */ 641*91f16700Schasinglulu PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID); 642*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 2); 643*91f16700Schasinglulu } 644*91f16700Schasinglulu 645*91f16700Schasinglulu /** 646*91f16700Schasinglulu * pm_secure_rsaaes() - Load the secure images. 647*91f16700Schasinglulu * @address_low: lower 32-bit Linear memory space address. 648*91f16700Schasinglulu * @address_high: higher 32-bit Linear memory space address. 649*91f16700Schasinglulu * @size: Number of 32bit words. 650*91f16700Schasinglulu * @flags: Additional flags or settings for the fpga operation. 651*91f16700Schasinglulu * 652*91f16700Schasinglulu * This function provides access to the xilsecure library to load the 653*91f16700Schasinglulu * authenticated, encrypted, and authenticated/encrypted images. 654*91f16700Schasinglulu * 655*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 656*91f16700Schasinglulu * 657*91f16700Schasinglulu */ 658*91f16700Schasinglulu enum pm_ret_status pm_secure_rsaaes(uint32_t address_low, 659*91f16700Schasinglulu uint32_t address_high, 660*91f16700Schasinglulu uint32_t size, 661*91f16700Schasinglulu uint32_t flags) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 664*91f16700Schasinglulu 665*91f16700Schasinglulu /* Send request to the PMU */ 666*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low, 667*91f16700Schasinglulu size, flags); 668*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 669*91f16700Schasinglulu } 670*91f16700Schasinglulu 671*91f16700Schasinglulu /** 672*91f16700Schasinglulu * pm_aes_engine() - Aes data blob encryption/decryption. 673*91f16700Schasinglulu * @address_low: lower 32-bit address of the AesParams structure. 674*91f16700Schasinglulu * @address_high: higher 32-bit address of the AesParams structure. 675*91f16700Schasinglulu * @value: Returned output value. 676*91f16700Schasinglulu * 677*91f16700Schasinglulu * This function provides access to the xilsecure library to 678*91f16700Schasinglulu * encrypt/decrypt data blobs. 679*91f16700Schasinglulu * 680*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 681*91f16700Schasinglulu * 682*91f16700Schasinglulu */ 683*91f16700Schasinglulu enum pm_ret_status pm_aes_engine(uint32_t address_high, 684*91f16700Schasinglulu uint32_t address_low, 685*91f16700Schasinglulu uint32_t *value) 686*91f16700Schasinglulu { 687*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 688*91f16700Schasinglulu 689*91f16700Schasinglulu /* Send request to the PMU */ 690*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low); 691*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 692*91f16700Schasinglulu } 693*91f16700Schasinglulu 694*91f16700Schasinglulu /** 695*91f16700Schasinglulu * pm_get_callbackdata() - Read from IPI response buffer. 696*91f16700Schasinglulu * @data: array of PAYLOAD_ARG_CNT elements. 697*91f16700Schasinglulu * @count: Number of values to return. 698*91f16700Schasinglulu * 699*91f16700Schasinglulu * Read value from ipi buffer response buffer. 700*91f16700Schasinglulu * Return: Returns status, either success or error. 701*91f16700Schasinglulu * 702*91f16700Schasinglulu */ 703*91f16700Schasinglulu enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count) 704*91f16700Schasinglulu { 705*91f16700Schasinglulu enum pm_ret_status ret = PM_RET_SUCCESS; 706*91f16700Schasinglulu /* Return if interrupt is not from PMU */ 707*91f16700Schasinglulu if (!pm_ipi_irq_status(primary_proc)) { 708*91f16700Schasinglulu return ret; 709*91f16700Schasinglulu } 710*91f16700Schasinglulu 711*91f16700Schasinglulu ret = pm_ipi_buff_read_callb(data, count); 712*91f16700Schasinglulu pm_ipi_irq_clear(primary_proc); 713*91f16700Schasinglulu return ret; 714*91f16700Schasinglulu } 715*91f16700Schasinglulu 716*91f16700Schasinglulu /** 717*91f16700Schasinglulu * pm_ioctl() - PM IOCTL API for device control and configs. 718*91f16700Schasinglulu * @nid: Node ID of the device. 719*91f16700Schasinglulu * @ioctl_id: ID of the requested IOCTL. 720*91f16700Schasinglulu * @arg1: Argument 1 to requested IOCTL call. 721*91f16700Schasinglulu * @arg2: Argument 2 to requested IOCTL call. 722*91f16700Schasinglulu * @value: Returned output value. 723*91f16700Schasinglulu * 724*91f16700Schasinglulu * This function calls IOCTL to firmware for device control and configuration. 725*91f16700Schasinglulu * 726*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 727*91f16700Schasinglulu * 728*91f16700Schasinglulu */ 729*91f16700Schasinglulu enum pm_ret_status pm_ioctl(enum pm_node_id nid, 730*91f16700Schasinglulu uint32_t ioctl_id, 731*91f16700Schasinglulu uint32_t arg1, 732*91f16700Schasinglulu uint32_t arg2, 733*91f16700Schasinglulu uint32_t *value) 734*91f16700Schasinglulu { 735*91f16700Schasinglulu return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value); 736*91f16700Schasinglulu } 737*91f16700Schasinglulu 738*91f16700Schasinglulu /** 739*91f16700Schasinglulu * fw_api_version() - Returns API version implemented in firmware. 740*91f16700Schasinglulu * @id: API ID to check. 741*91f16700Schasinglulu * @version: Returned supported API version. 742*91f16700Schasinglulu * @len: Number of words to be returned. 743*91f16700Schasinglulu * 744*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 745*91f16700Schasinglulu * 746*91f16700Schasinglulu */ 747*91f16700Schasinglulu static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version, 748*91f16700Schasinglulu uint32_t len) 749*91f16700Schasinglulu { 750*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 751*91f16700Schasinglulu 752*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id); 753*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, version, len); 754*91f16700Schasinglulu } 755*91f16700Schasinglulu 756*91f16700Schasinglulu /** 757*91f16700Schasinglulu * check_api_dependency() - API to check dependent EEMI API version. 758*91f16700Schasinglulu * @id: EEMI API ID to check. 759*91f16700Schasinglulu * 760*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 761*91f16700Schasinglulu * 762*91f16700Schasinglulu */ 763*91f16700Schasinglulu enum pm_ret_status check_api_dependency(uint8_t id) 764*91f16700Schasinglulu { 765*91f16700Schasinglulu uint8_t i; 766*91f16700Schasinglulu uint32_t version; 767*91f16700Schasinglulu int ret; 768*91f16700Schasinglulu 769*91f16700Schasinglulu for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) { 770*91f16700Schasinglulu if (api_dep_table[i].id == id) { 771*91f16700Schasinglulu if (api_dep_table[i].api_id == 0U) { 772*91f16700Schasinglulu break; 773*91f16700Schasinglulu } 774*91f16700Schasinglulu 775*91f16700Schasinglulu ret = fw_api_version(api_dep_table[i].api_id, 776*91f16700Schasinglulu &version, 1); 777*91f16700Schasinglulu if (ret != PM_RET_SUCCESS) { 778*91f16700Schasinglulu return ret; 779*91f16700Schasinglulu } 780*91f16700Schasinglulu 781*91f16700Schasinglulu /* Check if fw version matches TF-A expected version */ 782*91f16700Schasinglulu if (version != tfa_expected_ver_id[api_dep_table[i].api_id]) { 783*91f16700Schasinglulu return PM_RET_ERROR_NOTSUPPORTED; 784*91f16700Schasinglulu } 785*91f16700Schasinglulu } 786*91f16700Schasinglulu } 787*91f16700Schasinglulu 788*91f16700Schasinglulu return PM_RET_SUCCESS; 789*91f16700Schasinglulu } 790*91f16700Schasinglulu 791*91f16700Schasinglulu /** 792*91f16700Schasinglulu * feature_check_tfa() - These are API's completely implemented in TF-A. 793*91f16700Schasinglulu * @api_id: API ID to check. 794*91f16700Schasinglulu * @version: Returned supported API version. 795*91f16700Schasinglulu * @bit_mask: Returned supported IOCTL id version. 796*91f16700Schasinglulu * 797*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 798*91f16700Schasinglulu * 799*91f16700Schasinglulu */ 800*91f16700Schasinglulu static enum pm_ret_status feature_check_tfa(uint32_t api_id, uint32_t *version, 801*91f16700Schasinglulu uint32_t *bit_mask) 802*91f16700Schasinglulu { 803*91f16700Schasinglulu switch (api_id) { 804*91f16700Schasinglulu case PM_QUERY_DATA: 805*91f16700Schasinglulu *version = TFA_API_QUERY_DATA_VERSION; 806*91f16700Schasinglulu bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK); 807*91f16700Schasinglulu bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32); 808*91f16700Schasinglulu return PM_RET_SUCCESS; 809*91f16700Schasinglulu case PM_GET_CALLBACK_DATA: 810*91f16700Schasinglulu case PM_GET_TRUSTZONE_VERSION: 811*91f16700Schasinglulu case PM_SET_SUSPEND_MODE: 812*91f16700Schasinglulu *version = TFA_API_BASE_VERSION; 813*91f16700Schasinglulu return PM_RET_SUCCESS; 814*91f16700Schasinglulu default: 815*91f16700Schasinglulu return PM_RET_ERROR_NO_FEATURE; 816*91f16700Schasinglulu } 817*91f16700Schasinglulu } 818*91f16700Schasinglulu 819*91f16700Schasinglulu /** 820*91f16700Schasinglulu * get_tfa_version_for_partial_apis() - Return TF-A version for partially. 821*91f16700Schasinglulu * implemented APIs 822*91f16700Schasinglulu * @api_id: API ID to check. 823*91f16700Schasinglulu * @version: Returned supported API version. 824*91f16700Schasinglulu * 825*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 826*91f16700Schasinglulu * 827*91f16700Schasinglulu */ 828*91f16700Schasinglulu static enum pm_ret_status get_tfa_version_for_partial_apis(uint32_t api_id, 829*91f16700Schasinglulu uint32_t *version) 830*91f16700Schasinglulu { 831*91f16700Schasinglulu switch (api_id) { 832*91f16700Schasinglulu case PM_SELF_SUSPEND: 833*91f16700Schasinglulu case PM_REQ_WAKEUP: 834*91f16700Schasinglulu case PM_ABORT_SUSPEND: 835*91f16700Schasinglulu case PM_SET_WAKEUP_SOURCE: 836*91f16700Schasinglulu case PM_SYSTEM_SHUTDOWN: 837*91f16700Schasinglulu case PM_GET_API_VERSION: 838*91f16700Schasinglulu case PM_CLOCK_ENABLE: 839*91f16700Schasinglulu case PM_CLOCK_DISABLE: 840*91f16700Schasinglulu case PM_CLOCK_GETSTATE: 841*91f16700Schasinglulu case PM_CLOCK_SETDIVIDER: 842*91f16700Schasinglulu case PM_CLOCK_GETDIVIDER: 843*91f16700Schasinglulu case PM_CLOCK_SETPARENT: 844*91f16700Schasinglulu case PM_CLOCK_GETPARENT: 845*91f16700Schasinglulu case PM_PLL_SET_PARAMETER: 846*91f16700Schasinglulu case PM_PLL_GET_PARAMETER: 847*91f16700Schasinglulu case PM_PLL_SET_MODE: 848*91f16700Schasinglulu case PM_PLL_GET_MODE: 849*91f16700Schasinglulu case PM_REGISTER_ACCESS: 850*91f16700Schasinglulu *version = TFA_API_BASE_VERSION; 851*91f16700Schasinglulu return PM_RET_SUCCESS; 852*91f16700Schasinglulu case PM_FEATURE_CHECK: 853*91f16700Schasinglulu *version = FW_API_VERSION_2; 854*91f16700Schasinglulu return PM_RET_SUCCESS; 855*91f16700Schasinglulu default: 856*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 857*91f16700Schasinglulu } 858*91f16700Schasinglulu } 859*91f16700Schasinglulu 860*91f16700Schasinglulu /** 861*91f16700Schasinglulu * feature_check_partial() - These are API's partially implemented in 862*91f16700Schasinglulu * TF-A and firmware both. 863*91f16700Schasinglulu * @api_id: API ID to check. 864*91f16700Schasinglulu * @version: Returned supported API version. 865*91f16700Schasinglulu * 866*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 867*91f16700Schasinglulu * 868*91f16700Schasinglulu */ 869*91f16700Schasinglulu static enum pm_ret_status feature_check_partial(uint32_t api_id, 870*91f16700Schasinglulu uint32_t *version) 871*91f16700Schasinglulu { 872*91f16700Schasinglulu uint32_t status; 873*91f16700Schasinglulu 874*91f16700Schasinglulu switch (api_id) { 875*91f16700Schasinglulu case PM_SELF_SUSPEND: 876*91f16700Schasinglulu case PM_REQ_WAKEUP: 877*91f16700Schasinglulu case PM_ABORT_SUSPEND: 878*91f16700Schasinglulu case PM_SET_WAKEUP_SOURCE: 879*91f16700Schasinglulu case PM_SYSTEM_SHUTDOWN: 880*91f16700Schasinglulu case PM_GET_API_VERSION: 881*91f16700Schasinglulu case PM_CLOCK_ENABLE: 882*91f16700Schasinglulu case PM_CLOCK_DISABLE: 883*91f16700Schasinglulu case PM_CLOCK_GETSTATE: 884*91f16700Schasinglulu case PM_CLOCK_SETDIVIDER: 885*91f16700Schasinglulu case PM_CLOCK_GETDIVIDER: 886*91f16700Schasinglulu case PM_CLOCK_SETPARENT: 887*91f16700Schasinglulu case PM_CLOCK_GETPARENT: 888*91f16700Schasinglulu case PM_PLL_SET_PARAMETER: 889*91f16700Schasinglulu case PM_PLL_GET_PARAMETER: 890*91f16700Schasinglulu case PM_PLL_SET_MODE: 891*91f16700Schasinglulu case PM_PLL_GET_MODE: 892*91f16700Schasinglulu case PM_REGISTER_ACCESS: 893*91f16700Schasinglulu case PM_FEATURE_CHECK: 894*91f16700Schasinglulu status = check_api_dependency(api_id); 895*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 896*91f16700Schasinglulu return status; 897*91f16700Schasinglulu } 898*91f16700Schasinglulu return get_tfa_version_for_partial_apis(api_id, version); 899*91f16700Schasinglulu default: 900*91f16700Schasinglulu return PM_RET_ERROR_NO_FEATURE; 901*91f16700Schasinglulu } 902*91f16700Schasinglulu } 903*91f16700Schasinglulu 904*91f16700Schasinglulu /** 905*91f16700Schasinglulu * pm_feature_check() - Returns the supported API version if supported. 906*91f16700Schasinglulu * @api_id: API ID to check. 907*91f16700Schasinglulu * @version: Returned supported API version. 908*91f16700Schasinglulu * @bit_mask: Returned supported IOCTL id version. 909*91f16700Schasinglulu * @len: Number of bytes to be returned in bit_mask variable. 910*91f16700Schasinglulu * 911*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 912*91f16700Schasinglulu * 913*91f16700Schasinglulu */ 914*91f16700Schasinglulu enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version, 915*91f16700Schasinglulu uint32_t *bit_mask, uint8_t len) 916*91f16700Schasinglulu { 917*91f16700Schasinglulu uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U}; 918*91f16700Schasinglulu uint32_t status; 919*91f16700Schasinglulu 920*91f16700Schasinglulu /* Get API version implemented in TF-A */ 921*91f16700Schasinglulu status = feature_check_tfa(api_id, version, bit_mask); 922*91f16700Schasinglulu if (status != PM_RET_ERROR_NO_FEATURE) { 923*91f16700Schasinglulu return status; 924*91f16700Schasinglulu } 925*91f16700Schasinglulu 926*91f16700Schasinglulu /* Get API version implemented by firmware and TF-A both */ 927*91f16700Schasinglulu status = feature_check_partial(api_id, version); 928*91f16700Schasinglulu if (status != PM_RET_ERROR_NO_FEATURE) { 929*91f16700Schasinglulu return status; 930*91f16700Schasinglulu } 931*91f16700Schasinglulu 932*91f16700Schasinglulu /* Get API version implemented by firmware */ 933*91f16700Schasinglulu status = fw_api_version(api_id, ret_payload, 3); 934*91f16700Schasinglulu /* IOCTL call may return failure whose ID is not implemented in 935*91f16700Schasinglulu * firmware but implemented in TF-A 936*91f16700Schasinglulu */ 937*91f16700Schasinglulu if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) { 938*91f16700Schasinglulu return status; 939*91f16700Schasinglulu } 940*91f16700Schasinglulu 941*91f16700Schasinglulu *version = ret_payload[0]; 942*91f16700Schasinglulu 943*91f16700Schasinglulu /* Update IOCTL bit mask which are implemented in TF-A */ 944*91f16700Schasinglulu if ((api_id == PM_IOCTL) || (api_id == PM_GET_OP_CHARACTERISTIC)) { 945*91f16700Schasinglulu if (len < 2) { 946*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 947*91f16700Schasinglulu } 948*91f16700Schasinglulu bit_mask[0] = ret_payload[1]; 949*91f16700Schasinglulu bit_mask[1] = ret_payload[2]; 950*91f16700Schasinglulu if (api_id == PM_IOCTL) { 951*91f16700Schasinglulu /* Get IOCTL's implemented by TF-A */ 952*91f16700Schasinglulu status = tfa_ioctl_bitmask(bit_mask); 953*91f16700Schasinglulu } 954*91f16700Schasinglulu } else { 955*91f16700Schasinglulu /* Requires for MISRA */ 956*91f16700Schasinglulu } 957*91f16700Schasinglulu 958*91f16700Schasinglulu return status; 959*91f16700Schasinglulu } 960*91f16700Schasinglulu 961*91f16700Schasinglulu /** 962*91f16700Schasinglulu * pm_clock_get_max_divisor - PM call to get max divisor. 963*91f16700Schasinglulu * @clock_id: Clock ID. 964*91f16700Schasinglulu * @div_type: Divisor ID (TYPE_DIV1 or TYPE_DIV2). 965*91f16700Schasinglulu * @max_div: Maximum supported divisor. 966*91f16700Schasinglulu * 967*91f16700Schasinglulu * This function is used by master to get maximum supported value. 968*91f16700Schasinglulu * 969*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 970*91f16700Schasinglulu * 971*91f16700Schasinglulu */ 972*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id, 973*91f16700Schasinglulu uint8_t div_type, 974*91f16700Schasinglulu uint32_t *max_div) 975*91f16700Schasinglulu { 976*91f16700Schasinglulu return pm_api_clock_get_max_divisor(clock_id, div_type, max_div); 977*91f16700Schasinglulu } 978*91f16700Schasinglulu 979*91f16700Schasinglulu /** 980*91f16700Schasinglulu * pm_clock_get_num_clocks - PM call to request number of clocks. 981*91f16700Schasinglulu * @nclocks: Number of clocks. 982*91f16700Schasinglulu * 983*91f16700Schasinglulu * This function is used by master to get number of clocks. 984*91f16700Schasinglulu * 985*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 986*91f16700Schasinglulu * 987*91f16700Schasinglulu */ 988*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks) 989*91f16700Schasinglulu { 990*91f16700Schasinglulu return pm_api_clock_get_num_clocks(nclocks); 991*91f16700Schasinglulu } 992*91f16700Schasinglulu 993*91f16700Schasinglulu /** 994*91f16700Schasinglulu * pm_clock_get_name() - PM call to request a clock's name. 995*91f16700Schasinglulu * @clock_id: Clock ID. 996*91f16700Schasinglulu * @name: Name of clock (max 16 bytes). 997*91f16700Schasinglulu * 998*91f16700Schasinglulu * This function is used by master to get nmae of clock specified 999*91f16700Schasinglulu * by given clock ID. 1000*91f16700Schasinglulu * 1001*91f16700Schasinglulu */ 1002*91f16700Schasinglulu static void pm_clock_get_name(uint32_t clock_id, char *name) 1003*91f16700Schasinglulu { 1004*91f16700Schasinglulu pm_api_clock_get_name(clock_id, name); 1005*91f16700Schasinglulu } 1006*91f16700Schasinglulu 1007*91f16700Schasinglulu /** 1008*91f16700Schasinglulu * pm_clock_get_topology() - PM call to request a clock's topology. 1009*91f16700Schasinglulu * @clock_id: Clock ID. 1010*91f16700Schasinglulu * @index: Topology index for next toplogy node. 1011*91f16700Schasinglulu * @topology: Buffer to store nodes in topology and flags. 1012*91f16700Schasinglulu * 1013*91f16700Schasinglulu * This function is used by master to get topology information for the 1014*91f16700Schasinglulu * clock specified by given clock ID. Each response would return 3 1015*91f16700Schasinglulu * topology nodes. To get next nodes, caller needs to call this API with 1016*91f16700Schasinglulu * index of next node. Index starts from 0. 1017*91f16700Schasinglulu * 1018*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1019*91f16700Schasinglulu * 1020*91f16700Schasinglulu */ 1021*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id, 1022*91f16700Schasinglulu uint32_t index, 1023*91f16700Schasinglulu uint32_t *topology) 1024*91f16700Schasinglulu { 1025*91f16700Schasinglulu return pm_api_clock_get_topology(clock_id, index, topology); 1026*91f16700Schasinglulu } 1027*91f16700Schasinglulu 1028*91f16700Schasinglulu /** 1029*91f16700Schasinglulu * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor 1030*91f16700Schasinglulu * parameters for fixed clock. 1031*91f16700Schasinglulu * @clock_id: Clock ID. 1032*91f16700Schasinglulu * @mul: Multiplication value. 1033*91f16700Schasinglulu * @div: Divisor value. 1034*91f16700Schasinglulu * 1035*91f16700Schasinglulu * This function is used by master to get fixed factor parameers for the 1036*91f16700Schasinglulu * fixed clock. This API is application only for the fixed clock. 1037*91f16700Schasinglulu * 1038*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1039*91f16700Schasinglulu * 1040*91f16700Schasinglulu */ 1041*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id, 1042*91f16700Schasinglulu uint32_t *mul, 1043*91f16700Schasinglulu uint32_t *div) 1044*91f16700Schasinglulu { 1045*91f16700Schasinglulu return pm_api_clock_get_fixedfactor_params(clock_id, mul, div); 1046*91f16700Schasinglulu } 1047*91f16700Schasinglulu 1048*91f16700Schasinglulu /** 1049*91f16700Schasinglulu * pm_clock_get_parents() - PM call to request a clock's first 3 parents. 1050*91f16700Schasinglulu * @clock_id: Clock ID. 1051*91f16700Schasinglulu * @index: Index of next parent. 1052*91f16700Schasinglulu * @parents: Parents of the given clock. 1053*91f16700Schasinglulu * 1054*91f16700Schasinglulu * This function is used by master to get clock's parents information. 1055*91f16700Schasinglulu * This API will return 3 parents with a single response. To get other 1056*91f16700Schasinglulu * parents, master should call same API in loop with new parent index 1057*91f16700Schasinglulu * till error is returned. 1058*91f16700Schasinglulu * 1059*91f16700Schasinglulu * E.g First call should have index 0 which will return parents 0, 1 and 1060*91f16700Schasinglulu * 2. Next call, index should be 3 which will return parent 3,4 and 5 and 1061*91f16700Schasinglulu * so on. 1062*91f16700Schasinglulu * 1063*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1064*91f16700Schasinglulu * 1065*91f16700Schasinglulu */ 1066*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id, 1067*91f16700Schasinglulu uint32_t index, 1068*91f16700Schasinglulu uint32_t *parents) 1069*91f16700Schasinglulu { 1070*91f16700Schasinglulu return pm_api_clock_get_parents(clock_id, index, parents); 1071*91f16700Schasinglulu } 1072*91f16700Schasinglulu 1073*91f16700Schasinglulu /** 1074*91f16700Schasinglulu * pm_clock_get_attributes() - PM call to request a clock's attributes. 1075*91f16700Schasinglulu * @clock_id: Clock ID. 1076*91f16700Schasinglulu * @attr: Clock attributes. 1077*91f16700Schasinglulu * 1078*91f16700Schasinglulu * This function is used by master to get clock's attributes 1079*91f16700Schasinglulu * (e.g. valid, clock type, etc). 1080*91f16700Schasinglulu * 1081*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1082*91f16700Schasinglulu * 1083*91f16700Schasinglulu */ 1084*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id, 1085*91f16700Schasinglulu uint32_t *attr) 1086*91f16700Schasinglulu { 1087*91f16700Schasinglulu return pm_api_clock_get_attributes(clock_id, attr); 1088*91f16700Schasinglulu } 1089*91f16700Schasinglulu 1090*91f16700Schasinglulu /** 1091*91f16700Schasinglulu * pm_clock_gate() - Configure clock gate. 1092*91f16700Schasinglulu * @clock_id: Id of the clock to be configured. 1093*91f16700Schasinglulu * @enable: Flag 0=disable (gate the clock), !0=enable (activate the clock). 1094*91f16700Schasinglulu * 1095*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1096*91f16700Schasinglulu * PM controller (PMU). 1097*91f16700Schasinglulu * 1098*91f16700Schasinglulu */ 1099*91f16700Schasinglulu static enum pm_ret_status pm_clock_gate(uint32_t clock_id, 1100*91f16700Schasinglulu uint8_t enable) 1101*91f16700Schasinglulu { 1102*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1103*91f16700Schasinglulu enum pm_ret_status status; 1104*91f16700Schasinglulu enum pm_api_id api_id; 1105*91f16700Schasinglulu 1106*91f16700Schasinglulu /* Check if clock ID is valid and return an error if it is not */ 1107*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1108*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1109*91f16700Schasinglulu return status; 1110*91f16700Schasinglulu } 1111*91f16700Schasinglulu 1112*91f16700Schasinglulu if (enable) { 1113*91f16700Schasinglulu api_id = PM_CLOCK_ENABLE; 1114*91f16700Schasinglulu } else { 1115*91f16700Schasinglulu api_id = PM_CLOCK_DISABLE; 1116*91f16700Schasinglulu } 1117*91f16700Schasinglulu 1118*91f16700Schasinglulu /* Send request to the PMU */ 1119*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, api_id, clock_id); 1120*91f16700Schasinglulu status = pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1121*91f16700Schasinglulu 1122*91f16700Schasinglulu /* If action fails due to the lack of permissions filter the error */ 1123*91f16700Schasinglulu if (status == PM_RET_ERROR_ACCESS) { 1124*91f16700Schasinglulu status = PM_RET_SUCCESS; 1125*91f16700Schasinglulu } 1126*91f16700Schasinglulu 1127*91f16700Schasinglulu return status; 1128*91f16700Schasinglulu } 1129*91f16700Schasinglulu 1130*91f16700Schasinglulu /** 1131*91f16700Schasinglulu * pm_clock_enable() - Enable the clock for given id. 1132*91f16700Schasinglulu * @clock_id: Id of the clock to be enabled. 1133*91f16700Schasinglulu * 1134*91f16700Schasinglulu * This function is used by master to enable the clock 1135*91f16700Schasinglulu * including peripherals and PLL clocks. 1136*91f16700Schasinglulu * 1137*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1138*91f16700Schasinglulu * pm_clock_gate. 1139*91f16700Schasinglulu * 1140*91f16700Schasinglulu */ 1141*91f16700Schasinglulu enum pm_ret_status pm_clock_enable(uint32_t clock_id) 1142*91f16700Schasinglulu { 1143*91f16700Schasinglulu struct pm_pll *pll; 1144*91f16700Schasinglulu 1145*91f16700Schasinglulu /* First try to handle it as a PLL */ 1146*91f16700Schasinglulu pll = pm_clock_get_pll(clock_id); 1147*91f16700Schasinglulu if (pll) { 1148*91f16700Schasinglulu return pm_clock_pll_enable(pll); 1149*91f16700Schasinglulu } 1150*91f16700Schasinglulu 1151*91f16700Schasinglulu /* It's an on-chip clock, PMU should configure clock's gate */ 1152*91f16700Schasinglulu return pm_clock_gate(clock_id, 1); 1153*91f16700Schasinglulu } 1154*91f16700Schasinglulu 1155*91f16700Schasinglulu /** 1156*91f16700Schasinglulu * pm_clock_disable - Disable the clock for given id. 1157*91f16700Schasinglulu * @clock_id: Id of the clock to be disable. 1158*91f16700Schasinglulu * 1159*91f16700Schasinglulu * This function is used by master to disable the clock 1160*91f16700Schasinglulu * including peripherals and PLL clocks. 1161*91f16700Schasinglulu * 1162*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1163*91f16700Schasinglulu * pm_clock_gate 1164*91f16700Schasinglulu * 1165*91f16700Schasinglulu */ 1166*91f16700Schasinglulu enum pm_ret_status pm_clock_disable(uint32_t clock_id) 1167*91f16700Schasinglulu { 1168*91f16700Schasinglulu struct pm_pll *pll; 1169*91f16700Schasinglulu 1170*91f16700Schasinglulu /* First try to handle it as a PLL */ 1171*91f16700Schasinglulu pll = pm_clock_get_pll(clock_id); 1172*91f16700Schasinglulu if (pll) { 1173*91f16700Schasinglulu return pm_clock_pll_disable(pll); 1174*91f16700Schasinglulu } 1175*91f16700Schasinglulu 1176*91f16700Schasinglulu /* It's an on-chip clock, PMU should configure clock's gate */ 1177*91f16700Schasinglulu return pm_clock_gate(clock_id, 0); 1178*91f16700Schasinglulu } 1179*91f16700Schasinglulu 1180*91f16700Schasinglulu /** 1181*91f16700Schasinglulu * pm_clock_getstate - Get the clock state for given id. 1182*91f16700Schasinglulu * @clock_id: Id of the clock to be queried. 1183*91f16700Schasinglulu * @state: 1/0 (Enabled/Disabled). 1184*91f16700Schasinglulu * 1185*91f16700Schasinglulu * This function is used by master to get the state of clock 1186*91f16700Schasinglulu * including peripherals and PLL clocks. 1187*91f16700Schasinglulu * 1188*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1189*91f16700Schasinglulu * 1190*91f16700Schasinglulu */ 1191*91f16700Schasinglulu enum pm_ret_status pm_clock_getstate(uint32_t clock_id, 1192*91f16700Schasinglulu uint32_t *state) 1193*91f16700Schasinglulu { 1194*91f16700Schasinglulu struct pm_pll *pll; 1195*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1196*91f16700Schasinglulu enum pm_ret_status status; 1197*91f16700Schasinglulu 1198*91f16700Schasinglulu /* First try to handle it as a PLL */ 1199*91f16700Schasinglulu pll = pm_clock_get_pll(clock_id); 1200*91f16700Schasinglulu if (pll) 1201*91f16700Schasinglulu return pm_clock_pll_get_state(pll, state); 1202*91f16700Schasinglulu 1203*91f16700Schasinglulu /* Check if clock ID is a valid on-chip clock */ 1204*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1205*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1206*91f16700Schasinglulu return status; 1207*91f16700Schasinglulu } 1208*91f16700Schasinglulu 1209*91f16700Schasinglulu /* Send request to the PMU */ 1210*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id); 1211*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, state, 1); 1212*91f16700Schasinglulu } 1213*91f16700Schasinglulu 1214*91f16700Schasinglulu /** 1215*91f16700Schasinglulu * pm_clock_setdivider - Set the clock divider for given id. 1216*91f16700Schasinglulu * @clock_id: Id of the clock. 1217*91f16700Schasinglulu * @divider: divider value. 1218*91f16700Schasinglulu * 1219*91f16700Schasinglulu * This function is used by master to set divider for any clock 1220*91f16700Schasinglulu * to achieve desired rate. 1221*91f16700Schasinglulu * 1222*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1223*91f16700Schasinglulu * 1224*91f16700Schasinglulu */ 1225*91f16700Schasinglulu enum pm_ret_status pm_clock_setdivider(uint32_t clock_id, 1226*91f16700Schasinglulu uint32_t divider) 1227*91f16700Schasinglulu { 1228*91f16700Schasinglulu enum pm_ret_status status; 1229*91f16700Schasinglulu enum pm_node_id nid; 1230*91f16700Schasinglulu enum pm_clock_div_id div_id; 1231*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1232*91f16700Schasinglulu const uint32_t div0 = 0xFFFF0000; 1233*91f16700Schasinglulu const uint32_t div1 = 0x0000FFFF; 1234*91f16700Schasinglulu uint32_t val; 1235*91f16700Schasinglulu 1236*91f16700Schasinglulu /* Get PLL node ID using PLL clock ID */ 1237*91f16700Schasinglulu status = pm_clock_get_pll_node_id(clock_id, &nid); 1238*91f16700Schasinglulu if (status == PM_RET_SUCCESS) { 1239*91f16700Schasinglulu return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider); 1240*91f16700Schasinglulu } 1241*91f16700Schasinglulu 1242*91f16700Schasinglulu /* Check if clock ID is a valid on-chip clock */ 1243*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1244*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1245*91f16700Schasinglulu return status; 1246*91f16700Schasinglulu } 1247*91f16700Schasinglulu 1248*91f16700Schasinglulu if (div0 == (divider & div0)) { 1249*91f16700Schasinglulu div_id = PM_CLOCK_DIV0_ID; 1250*91f16700Schasinglulu val = divider & ~div0; 1251*91f16700Schasinglulu } else if (div1 == (divider & div1)) { 1252*91f16700Schasinglulu div_id = PM_CLOCK_DIV1_ID; 1253*91f16700Schasinglulu val = (divider & ~div1) >> 16; 1254*91f16700Schasinglulu } else { 1255*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1256*91f16700Schasinglulu } 1257*91f16700Schasinglulu 1258*91f16700Schasinglulu /* Send request to the PMU */ 1259*91f16700Schasinglulu PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val); 1260*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1261*91f16700Schasinglulu } 1262*91f16700Schasinglulu 1263*91f16700Schasinglulu /** 1264*91f16700Schasinglulu * pm_clock_getdivider - Get the clock divider for given id. 1265*91f16700Schasinglulu * @clock_id: Id of the clock. 1266*91f16700Schasinglulu * @divider: divider value. 1267*91f16700Schasinglulu * 1268*91f16700Schasinglulu * This function is used by master to get divider values 1269*91f16700Schasinglulu * for any clock. 1270*91f16700Schasinglulu * 1271*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1272*91f16700Schasinglulu * 1273*91f16700Schasinglulu */ 1274*91f16700Schasinglulu enum pm_ret_status pm_clock_getdivider(uint32_t clock_id, 1275*91f16700Schasinglulu uint32_t *divider) 1276*91f16700Schasinglulu { 1277*91f16700Schasinglulu enum pm_ret_status status; 1278*91f16700Schasinglulu enum pm_node_id nid; 1279*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1280*91f16700Schasinglulu uint32_t val; 1281*91f16700Schasinglulu 1282*91f16700Schasinglulu /* Get PLL node ID using PLL clock ID */ 1283*91f16700Schasinglulu status = pm_clock_get_pll_node_id(clock_id, &nid); 1284*91f16700Schasinglulu if (status == PM_RET_SUCCESS) { 1285*91f16700Schasinglulu return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider); 1286*91f16700Schasinglulu } 1287*91f16700Schasinglulu 1288*91f16700Schasinglulu /* Check if clock ID is a valid on-chip clock */ 1289*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1290*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1291*91f16700Schasinglulu return status; 1292*91f16700Schasinglulu } 1293*91f16700Schasinglulu 1294*91f16700Schasinglulu if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) { 1295*91f16700Schasinglulu /* Send request to the PMU to get div0 */ 1296*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id, 1297*91f16700Schasinglulu PM_CLOCK_DIV0_ID); 1298*91f16700Schasinglulu status = pm_ipi_send_sync(primary_proc, payload, &val, 1); 1299*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1300*91f16700Schasinglulu return status; 1301*91f16700Schasinglulu } 1302*91f16700Schasinglulu *divider = val; 1303*91f16700Schasinglulu } 1304*91f16700Schasinglulu 1305*91f16700Schasinglulu if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) { 1306*91f16700Schasinglulu /* Send request to the PMU to get div1 */ 1307*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id, 1308*91f16700Schasinglulu PM_CLOCK_DIV1_ID); 1309*91f16700Schasinglulu status = pm_ipi_send_sync(primary_proc, payload, &val, 1); 1310*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1311*91f16700Schasinglulu return status; 1312*91f16700Schasinglulu } 1313*91f16700Schasinglulu *divider |= val << 16; 1314*91f16700Schasinglulu } 1315*91f16700Schasinglulu 1316*91f16700Schasinglulu return status; 1317*91f16700Schasinglulu } 1318*91f16700Schasinglulu 1319*91f16700Schasinglulu /** 1320*91f16700Schasinglulu * pm_clock_setparent - Set the clock parent for given id. 1321*91f16700Schasinglulu * @clock_id: Id of the clock. 1322*91f16700Schasinglulu * @parent_index: Index of the parent clock into clock's parents array. 1323*91f16700Schasinglulu * 1324*91f16700Schasinglulu * This function is used by master to set parent for any clock. 1325*91f16700Schasinglulu * 1326*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1327*91f16700Schasinglulu * 1328*91f16700Schasinglulu */ 1329*91f16700Schasinglulu enum pm_ret_status pm_clock_setparent(uint32_t clock_id, 1330*91f16700Schasinglulu uint32_t parent_index) 1331*91f16700Schasinglulu { 1332*91f16700Schasinglulu struct pm_pll *pll; 1333*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1334*91f16700Schasinglulu enum pm_ret_status status; 1335*91f16700Schasinglulu 1336*91f16700Schasinglulu /* First try to handle it as a PLL */ 1337*91f16700Schasinglulu pll = pm_clock_get_pll_by_related_clk(clock_id); 1338*91f16700Schasinglulu if (pll) { 1339*91f16700Schasinglulu return pm_clock_pll_set_parent(pll, clock_id, parent_index); 1340*91f16700Schasinglulu } 1341*91f16700Schasinglulu 1342*91f16700Schasinglulu /* Check if clock ID is a valid on-chip clock */ 1343*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1344*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1345*91f16700Schasinglulu return status; 1346*91f16700Schasinglulu } 1347*91f16700Schasinglulu 1348*91f16700Schasinglulu /* Send request to the PMU */ 1349*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index); 1350*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1351*91f16700Schasinglulu } 1352*91f16700Schasinglulu 1353*91f16700Schasinglulu /** 1354*91f16700Schasinglulu * pm_clock_getparent - Get the clock parent for given id. 1355*91f16700Schasinglulu * @clock_id: Id of the clock. 1356*91f16700Schasinglulu * @parent_index: parent index. 1357*91f16700Schasinglulu * 1358*91f16700Schasinglulu * This function is used by master to get parent index 1359*91f16700Schasinglulu * for any clock. 1360*91f16700Schasinglulu * 1361*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1362*91f16700Schasinglulu * 1363*91f16700Schasinglulu */ 1364*91f16700Schasinglulu enum pm_ret_status pm_clock_getparent(uint32_t clock_id, 1365*91f16700Schasinglulu uint32_t *parent_index) 1366*91f16700Schasinglulu { 1367*91f16700Schasinglulu struct pm_pll *pll; 1368*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1369*91f16700Schasinglulu enum pm_ret_status status; 1370*91f16700Schasinglulu 1371*91f16700Schasinglulu /* First try to handle it as a PLL */ 1372*91f16700Schasinglulu pll = pm_clock_get_pll_by_related_clk(clock_id); 1373*91f16700Schasinglulu if (pll) { 1374*91f16700Schasinglulu return pm_clock_pll_get_parent(pll, clock_id, parent_index); 1375*91f16700Schasinglulu } 1376*91f16700Schasinglulu 1377*91f16700Schasinglulu /* Check if clock ID is a valid on-chip clock */ 1378*91f16700Schasinglulu status = pm_clock_id_is_valid(clock_id); 1379*91f16700Schasinglulu if (status != PM_RET_SUCCESS) { 1380*91f16700Schasinglulu return status; 1381*91f16700Schasinglulu } 1382*91f16700Schasinglulu 1383*91f16700Schasinglulu /* Send request to the PMU */ 1384*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id); 1385*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, parent_index, 1); 1386*91f16700Schasinglulu } 1387*91f16700Schasinglulu 1388*91f16700Schasinglulu /** 1389*91f16700Schasinglulu * pm_pinctrl_get_num_pins - PM call to request number of pins. 1390*91f16700Schasinglulu * @npins: Number of pins. 1391*91f16700Schasinglulu * 1392*91f16700Schasinglulu * This function is used by master to get number of pins. 1393*91f16700Schasinglulu * 1394*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1395*91f16700Schasinglulu * 1396*91f16700Schasinglulu */ 1397*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins) 1398*91f16700Schasinglulu { 1399*91f16700Schasinglulu return pm_api_pinctrl_get_num_pins(npins); 1400*91f16700Schasinglulu } 1401*91f16700Schasinglulu 1402*91f16700Schasinglulu /** 1403*91f16700Schasinglulu * pm_pinctrl_get_num_functions - PM call to request number of functions. 1404*91f16700Schasinglulu * @nfuncs: Number of functions. 1405*91f16700Schasinglulu * 1406*91f16700Schasinglulu * This function is used by master to get number of functions. 1407*91f16700Schasinglulu * 1408*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1409*91f16700Schasinglulu * 1410*91f16700Schasinglulu */ 1411*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs) 1412*91f16700Schasinglulu { 1413*91f16700Schasinglulu return pm_api_pinctrl_get_num_functions(nfuncs); 1414*91f16700Schasinglulu } 1415*91f16700Schasinglulu 1416*91f16700Schasinglulu /** 1417*91f16700Schasinglulu * pm_pinctrl_get_num_function_groups - PM call to request number of 1418*91f16700Schasinglulu * function groups. 1419*91f16700Schasinglulu * @fid: Id of function. 1420*91f16700Schasinglulu * @ngroups: Number of function groups. 1421*91f16700Schasinglulu * 1422*91f16700Schasinglulu * This function is used by master to get number of function groups specified 1423*91f16700Schasinglulu * by given function Id. 1424*91f16700Schasinglulu * 1425*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1426*91f16700Schasinglulu * 1427*91f16700Schasinglulu */ 1428*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid, 1429*91f16700Schasinglulu uint32_t *ngroups) 1430*91f16700Schasinglulu { 1431*91f16700Schasinglulu return pm_api_pinctrl_get_num_func_groups(fid, ngroups); 1432*91f16700Schasinglulu } 1433*91f16700Schasinglulu 1434*91f16700Schasinglulu /** 1435*91f16700Schasinglulu * pm_pinctrl_get_function_name - PM call to request function name. 1436*91f16700Schasinglulu * @fid: Id of function. 1437*91f16700Schasinglulu * @name: Name of function. 1438*91f16700Schasinglulu * 1439*91f16700Schasinglulu * This function is used by master to get name of function specified 1440*91f16700Schasinglulu * by given function Id. 1441*91f16700Schasinglulu * 1442*91f16700Schasinglulu */ 1443*91f16700Schasinglulu static void pm_pinctrl_get_function_name(uint32_t fid, char *name) 1444*91f16700Schasinglulu { 1445*91f16700Schasinglulu pm_api_pinctrl_get_function_name(fid, name); 1446*91f16700Schasinglulu } 1447*91f16700Schasinglulu 1448*91f16700Schasinglulu /** 1449*91f16700Schasinglulu * pm_pinctrl_get_function_groups - PM call to request function groups. 1450*91f16700Schasinglulu * @fid: Id of function. 1451*91f16700Schasinglulu * @index: Index of next function groups. 1452*91f16700Schasinglulu * @groups: Function groups. 1453*91f16700Schasinglulu * 1454*91f16700Schasinglulu * This function is used by master to get function groups specified 1455*91f16700Schasinglulu * by given function Id. This API will return 6 function groups with 1456*91f16700Schasinglulu * a single response. To get other function groups, master should call 1457*91f16700Schasinglulu * same API in loop with new function groups index till error is returned. 1458*91f16700Schasinglulu * 1459*91f16700Schasinglulu * E.g First call should have index 0 which will return function groups 1460*91f16700Schasinglulu * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return 1461*91f16700Schasinglulu * function groups 6, 7, 8, 9, 10 and 11 and so on. 1462*91f16700Schasinglulu * 1463*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1464*91f16700Schasinglulu * 1465*91f16700Schasinglulu */ 1466*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid, 1467*91f16700Schasinglulu uint32_t index, 1468*91f16700Schasinglulu uint16_t *groups) 1469*91f16700Schasinglulu { 1470*91f16700Schasinglulu return pm_api_pinctrl_get_function_groups(fid, index, groups); 1471*91f16700Schasinglulu } 1472*91f16700Schasinglulu 1473*91f16700Schasinglulu /** 1474*91f16700Schasinglulu * pm_pinctrl_get_pin_groups - PM call to request pin groups. 1475*91f16700Schasinglulu * @pin_id: Id of pin. 1476*91f16700Schasinglulu * @index: Index of next pin groups. 1477*91f16700Schasinglulu * @groups: pin groups. 1478*91f16700Schasinglulu * 1479*91f16700Schasinglulu * This function is used by master to get pin groups specified 1480*91f16700Schasinglulu * by given pin Id. This API will return 6 pin groups with 1481*91f16700Schasinglulu * a single response. To get other pin groups, master should call 1482*91f16700Schasinglulu * same API in loop with new pin groups index till error is returned. 1483*91f16700Schasinglulu * 1484*91f16700Schasinglulu * E.g First call should have index 0 which will return pin groups 1485*91f16700Schasinglulu * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return 1486*91f16700Schasinglulu * pin groups 6, 7, 8, 9, 10 and 11 and so on. 1487*91f16700Schasinglulu * 1488*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1489*91f16700Schasinglulu * 1490*91f16700Schasinglulu */ 1491*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id, 1492*91f16700Schasinglulu uint32_t index, 1493*91f16700Schasinglulu uint16_t *groups) 1494*91f16700Schasinglulu { 1495*91f16700Schasinglulu return pm_api_pinctrl_get_pin_groups(pin_id, index, groups); 1496*91f16700Schasinglulu } 1497*91f16700Schasinglulu 1498*91f16700Schasinglulu /** 1499*91f16700Schasinglulu * pm_query_data() - PM API for querying firmware data. 1500*91f16700Schasinglulu * @qid: represents the query identifiers for PM. 1501*91f16700Schasinglulu * @arg1: Argument 1 to requested IOCTL call. 1502*91f16700Schasinglulu * @arg2: Argument 2 to requested IOCTL call. 1503*91f16700Schasinglulu * @arg3: Argument 3 to requested IOCTL call. 1504*91f16700Schasinglulu * @data: Returned output data. 1505*91f16700Schasinglulu * 1506*91f16700Schasinglulu * This function returns requested data. 1507*91f16700Schasinglulu * 1508*91f16700Schasinglulu */ 1509*91f16700Schasinglulu void pm_query_data(enum pm_query_ids qid, uint32_t arg1, uint32_t arg2, 1510*91f16700Schasinglulu uint32_t arg3, uint32_t *data) 1511*91f16700Schasinglulu { 1512*91f16700Schasinglulu switch (qid) { 1513*91f16700Schasinglulu case PM_QID_CLOCK_GET_NAME: 1514*91f16700Schasinglulu pm_clock_get_name(arg1, (char *)data); 1515*91f16700Schasinglulu break; 1516*91f16700Schasinglulu case PM_QID_CLOCK_GET_TOPOLOGY: 1517*91f16700Schasinglulu data[0] = pm_clock_get_topology(arg1, arg2, &data[1]); 1518*91f16700Schasinglulu break; 1519*91f16700Schasinglulu case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS: 1520*91f16700Schasinglulu data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1], 1521*91f16700Schasinglulu &data[2]); 1522*91f16700Schasinglulu break; 1523*91f16700Schasinglulu case PM_QID_CLOCK_GET_PARENTS: 1524*91f16700Schasinglulu data[0] = pm_clock_get_parents(arg1, arg2, &data[1]); 1525*91f16700Schasinglulu break; 1526*91f16700Schasinglulu case PM_QID_CLOCK_GET_ATTRIBUTES: 1527*91f16700Schasinglulu data[0] = pm_clock_get_attributes(arg1, &data[1]); 1528*91f16700Schasinglulu break; 1529*91f16700Schasinglulu case PM_QID_PINCTRL_GET_NUM_PINS: 1530*91f16700Schasinglulu data[0] = pm_pinctrl_get_num_pins(&data[1]); 1531*91f16700Schasinglulu break; 1532*91f16700Schasinglulu case PM_QID_PINCTRL_GET_NUM_FUNCTIONS: 1533*91f16700Schasinglulu data[0] = pm_pinctrl_get_num_functions(&data[1]); 1534*91f16700Schasinglulu break; 1535*91f16700Schasinglulu case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS: 1536*91f16700Schasinglulu data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]); 1537*91f16700Schasinglulu break; 1538*91f16700Schasinglulu case PM_QID_PINCTRL_GET_FUNCTION_NAME: 1539*91f16700Schasinglulu pm_pinctrl_get_function_name(arg1, (char *)data); 1540*91f16700Schasinglulu break; 1541*91f16700Schasinglulu case PM_QID_PINCTRL_GET_FUNCTION_GROUPS: 1542*91f16700Schasinglulu data[0] = pm_pinctrl_get_function_groups(arg1, arg2, 1543*91f16700Schasinglulu (uint16_t *)&data[1]); 1544*91f16700Schasinglulu break; 1545*91f16700Schasinglulu case PM_QID_PINCTRL_GET_PIN_GROUPS: 1546*91f16700Schasinglulu data[0] = pm_pinctrl_get_pin_groups(arg1, arg2, 1547*91f16700Schasinglulu (uint16_t *)&data[1]); 1548*91f16700Schasinglulu break; 1549*91f16700Schasinglulu case PM_QID_CLOCK_GET_NUM_CLOCKS: 1550*91f16700Schasinglulu data[0] = pm_clock_get_num_clocks(&data[1]); 1551*91f16700Schasinglulu break; 1552*91f16700Schasinglulu 1553*91f16700Schasinglulu case PM_QID_CLOCK_GET_MAX_DIVISOR: 1554*91f16700Schasinglulu data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]); 1555*91f16700Schasinglulu break; 1556*91f16700Schasinglulu default: 1557*91f16700Schasinglulu data[0] = PM_RET_ERROR_ARGS; 1558*91f16700Schasinglulu WARN("Unimplemented query service call: 0x%x\n", qid); 1559*91f16700Schasinglulu break; 1560*91f16700Schasinglulu } 1561*91f16700Schasinglulu } 1562*91f16700Schasinglulu 1563*91f16700Schasinglulu enum pm_ret_status pm_sha_hash(uint32_t address_high, 1564*91f16700Schasinglulu uint32_t address_low, 1565*91f16700Schasinglulu uint32_t size, 1566*91f16700Schasinglulu uint32_t flags) 1567*91f16700Schasinglulu { 1568*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1569*91f16700Schasinglulu 1570*91f16700Schasinglulu /* Send request to the PMU */ 1571*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low, 1572*91f16700Schasinglulu size, flags); 1573*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1574*91f16700Schasinglulu } 1575*91f16700Schasinglulu 1576*91f16700Schasinglulu enum pm_ret_status pm_rsa_core(uint32_t address_high, 1577*91f16700Schasinglulu uint32_t address_low, 1578*91f16700Schasinglulu uint32_t size, 1579*91f16700Schasinglulu uint32_t flags) 1580*91f16700Schasinglulu { 1581*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1582*91f16700Schasinglulu 1583*91f16700Schasinglulu /* Send request to the PMU */ 1584*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low, 1585*91f16700Schasinglulu size, flags); 1586*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1587*91f16700Schasinglulu } 1588*91f16700Schasinglulu 1589*91f16700Schasinglulu enum pm_ret_status pm_secure_image(uint32_t address_low, 1590*91f16700Schasinglulu uint32_t address_high, 1591*91f16700Schasinglulu uint32_t key_lo, 1592*91f16700Schasinglulu uint32_t key_hi, 1593*91f16700Schasinglulu uint32_t *value) 1594*91f16700Schasinglulu { 1595*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1596*91f16700Schasinglulu 1597*91f16700Schasinglulu /* Send request to the PMU */ 1598*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low, 1599*91f16700Schasinglulu key_hi, key_lo); 1600*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 2); 1601*91f16700Schasinglulu } 1602*91f16700Schasinglulu 1603*91f16700Schasinglulu /** 1604*91f16700Schasinglulu * pm_fpga_read - Perform the fpga configuration readback. 1605*91f16700Schasinglulu * @reg_numframes: Configuration register offset (or) Number of frames to read. 1606*91f16700Schasinglulu * @address_low: lower 32-bit Linear memory space address. 1607*91f16700Schasinglulu * @address_high: higher 32-bit Linear memory space address. 1608*91f16700Schasinglulu * @readback_type: Type of fpga readback operation. 1609*91f16700Schasinglulu * 0 -- Configuration Register readback. 1610*91f16700Schasinglulu * 1 -- Configuration Data readback. 1611*91f16700Schasinglulu * @value: Value to read. 1612*91f16700Schasinglulu * 1613*91f16700Schasinglulu * This function provides access to the xilfpga library to read 1614*91f16700Schasinglulu * the PL configuration. 1615*91f16700Schasinglulu * 1616*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1617*91f16700Schasinglulu * 1618*91f16700Schasinglulu */ 1619*91f16700Schasinglulu enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, 1620*91f16700Schasinglulu uint32_t address_low, 1621*91f16700Schasinglulu uint32_t address_high, 1622*91f16700Schasinglulu uint32_t readback_type, 1623*91f16700Schasinglulu uint32_t *value) 1624*91f16700Schasinglulu { 1625*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1626*91f16700Schasinglulu 1627*91f16700Schasinglulu /* Send request to the PMU */ 1628*91f16700Schasinglulu PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low, 1629*91f16700Schasinglulu address_high, readback_type); 1630*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 1631*91f16700Schasinglulu } 1632*91f16700Schasinglulu 1633*91f16700Schasinglulu /* 1634*91f16700Schasinglulu * pm_pll_set_parameter() - Set the PLL parameter value. 1635*91f16700Schasinglulu * @nid: Node id of the target PLL. 1636*91f16700Schasinglulu * @param_id: ID of the PLL parameter. 1637*91f16700Schasinglulu * @value: Parameter value to be set. 1638*91f16700Schasinglulu * 1639*91f16700Schasinglulu * Setting the parameter will have physical effect once the PLL mode is set to 1640*91f16700Schasinglulu * integer or fractional. 1641*91f16700Schasinglulu * 1642*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1643*91f16700Schasinglulu * PM controller (PMU). 1644*91f16700Schasinglulu * 1645*91f16700Schasinglulu */ 1646*91f16700Schasinglulu enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid, 1647*91f16700Schasinglulu enum pm_pll_param param_id, 1648*91f16700Schasinglulu uint32_t value) 1649*91f16700Schasinglulu { 1650*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1651*91f16700Schasinglulu 1652*91f16700Schasinglulu /* Check if given node ID is a PLL node */ 1653*91f16700Schasinglulu if (nid < NODE_APLL || nid > NODE_IOPLL) { 1654*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1655*91f16700Schasinglulu } 1656*91f16700Schasinglulu 1657*91f16700Schasinglulu /* Check if parameter ID is valid and return an error if it's not */ 1658*91f16700Schasinglulu if (param_id >= PM_PLL_PARAM_MAX) { 1659*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1660*91f16700Schasinglulu } 1661*91f16700Schasinglulu 1662*91f16700Schasinglulu /* Send request to the PMU */ 1663*91f16700Schasinglulu PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value); 1664*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1665*91f16700Schasinglulu } 1666*91f16700Schasinglulu 1667*91f16700Schasinglulu /** 1668*91f16700Schasinglulu * pm_pll_get_parameter() - Get the PLL parameter value. 1669*91f16700Schasinglulu * @nid: Node id of the target PLL. 1670*91f16700Schasinglulu * @param_id: ID of the PLL parameter. 1671*91f16700Schasinglulu * @value: Location to store the parameter value. 1672*91f16700Schasinglulu * 1673*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1674*91f16700Schasinglulu * PM controller (PMU). 1675*91f16700Schasinglulu * 1676*91f16700Schasinglulu */ 1677*91f16700Schasinglulu enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid, 1678*91f16700Schasinglulu enum pm_pll_param param_id, 1679*91f16700Schasinglulu uint32_t *value) 1680*91f16700Schasinglulu { 1681*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1682*91f16700Schasinglulu 1683*91f16700Schasinglulu /* Check if given node ID is a PLL node */ 1684*91f16700Schasinglulu if (nid < NODE_APLL || nid > NODE_IOPLL) { 1685*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1686*91f16700Schasinglulu } 1687*91f16700Schasinglulu 1688*91f16700Schasinglulu /* Check if parameter ID is valid and return an error if it's not */ 1689*91f16700Schasinglulu if (param_id >= PM_PLL_PARAM_MAX) { 1690*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1691*91f16700Schasinglulu } 1692*91f16700Schasinglulu 1693*91f16700Schasinglulu /* Send request to the PMU */ 1694*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id); 1695*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 1696*91f16700Schasinglulu } 1697*91f16700Schasinglulu 1698*91f16700Schasinglulu /** 1699*91f16700Schasinglulu * pm_pll_set_mode() - Set the PLL mode. 1700*91f16700Schasinglulu * @nid: Node id of the target PLL. 1701*91f16700Schasinglulu * @mode: PLL mode to be set. 1702*91f16700Schasinglulu * 1703*91f16700Schasinglulu * If reset mode is set the PM controller will first bypass the PLL and then 1704*91f16700Schasinglulu * assert the reset. If integer or fractional mode is set the PM controller will 1705*91f16700Schasinglulu * ensure that the complete PLL programming sequence is satisfied. After this 1706*91f16700Schasinglulu * function returns success the PLL is locked and its bypass is deasserted. 1707*91f16700Schasinglulu * 1708*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1709*91f16700Schasinglulu * PM controller (PMU). 1710*91f16700Schasinglulu * 1711*91f16700Schasinglulu */ 1712*91f16700Schasinglulu enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode) 1713*91f16700Schasinglulu { 1714*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1715*91f16700Schasinglulu 1716*91f16700Schasinglulu /* Check if given node ID is a PLL node */ 1717*91f16700Schasinglulu if (nid < NODE_APLL || nid > NODE_IOPLL) { 1718*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1719*91f16700Schasinglulu } 1720*91f16700Schasinglulu 1721*91f16700Schasinglulu /* Check if PLL mode is valid */ 1722*91f16700Schasinglulu if (mode >= PM_PLL_MODE_MAX) { 1723*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1724*91f16700Schasinglulu } 1725*91f16700Schasinglulu 1726*91f16700Schasinglulu /* Send request to the PMU */ 1727*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode); 1728*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, NULL, 0); 1729*91f16700Schasinglulu } 1730*91f16700Schasinglulu 1731*91f16700Schasinglulu /** 1732*91f16700Schasinglulu * pm_pll_get_mode() - Get the PLL mode. 1733*91f16700Schasinglulu * @nid: Node id of the target PLL. 1734*91f16700Schasinglulu * @mode: Location to store the mode of the PLL. 1735*91f16700Schasinglulu * 1736*91f16700Schasinglulu * Return: Error if an argument is not valid or status as returned by the 1737*91f16700Schasinglulu * PM controller (PMU). 1738*91f16700Schasinglulu * 1739*91f16700Schasinglulu */ 1740*91f16700Schasinglulu enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode) 1741*91f16700Schasinglulu { 1742*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1743*91f16700Schasinglulu 1744*91f16700Schasinglulu /* Check if given node ID is a PLL node */ 1745*91f16700Schasinglulu if (nid < NODE_APLL || nid > NODE_IOPLL) { 1746*91f16700Schasinglulu return PM_RET_ERROR_ARGS; 1747*91f16700Schasinglulu } 1748*91f16700Schasinglulu 1749*91f16700Schasinglulu /* Send request to the PMU */ 1750*91f16700Schasinglulu PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid); 1751*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, mode, 1); 1752*91f16700Schasinglulu } 1753*91f16700Schasinglulu 1754*91f16700Schasinglulu /** 1755*91f16700Schasinglulu * pm_register_access() - PM API for register read/write access data. 1756*91f16700Schasinglulu * @register_access_id: Register_access_id which says register read/write. 1757*91f16700Schasinglulu * @address: Address of the register to be accessed. 1758*91f16700Schasinglulu * @mask: Mask value to be used while writing value. 1759*91f16700Schasinglulu * @value: Value to be written to register. 1760*91f16700Schasinglulu * @out: Returned output data. 1761*91f16700Schasinglulu * 1762*91f16700Schasinglulu * This function returns requested data. 1763*91f16700Schasinglulu * 1764*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1765*91f16700Schasinglulu * 1766*91f16700Schasinglulu */ 1767*91f16700Schasinglulu enum pm_ret_status pm_register_access(uint32_t register_access_id, 1768*91f16700Schasinglulu uint32_t address, 1769*91f16700Schasinglulu uint32_t mask, 1770*91f16700Schasinglulu uint32_t value, 1771*91f16700Schasinglulu uint32_t *out) 1772*91f16700Schasinglulu { 1773*91f16700Schasinglulu enum pm_ret_status ret; 1774*91f16700Schasinglulu 1775*91f16700Schasinglulu if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) && 1776*91f16700Schasinglulu ((CSUDMA_BASE & address) != CSUDMA_BASE) && 1777*91f16700Schasinglulu ((RSA_CORE_BASE & address) != RSA_CORE_BASE) && 1778*91f16700Schasinglulu ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) { 1779*91f16700Schasinglulu return PM_RET_ERROR_ACCESS; 1780*91f16700Schasinglulu } 1781*91f16700Schasinglulu 1782*91f16700Schasinglulu switch (register_access_id) { 1783*91f16700Schasinglulu case CONFIG_REG_WRITE: 1784*91f16700Schasinglulu ret = pm_mmio_write(address, mask, value); 1785*91f16700Schasinglulu break; 1786*91f16700Schasinglulu case CONFIG_REG_READ: 1787*91f16700Schasinglulu ret = pm_mmio_read(address, out); 1788*91f16700Schasinglulu break; 1789*91f16700Schasinglulu default: 1790*91f16700Schasinglulu ret = PM_RET_ERROR_ARGS; 1791*91f16700Schasinglulu WARN("Unimplemented register_access call\n\r"); 1792*91f16700Schasinglulu break; 1793*91f16700Schasinglulu } 1794*91f16700Schasinglulu return ret; 1795*91f16700Schasinglulu } 1796*91f16700Schasinglulu 1797*91f16700Schasinglulu /** 1798*91f16700Schasinglulu * pm_efuse_access() - To program or read efuse bits. This function provides 1799*91f16700Schasinglulu * access to the xilskey library to program/read 1800*91f16700Schasinglulu * efuse bits. 1801*91f16700Schasinglulu * @address_low: lower 32-bit Linear memory space address. 1802*91f16700Schasinglulu * @address_high: higher 32-bit Linear memory space address. 1803*91f16700Schasinglulu * @value: Returned output value. 1804*91f16700Schasinglulu * 1805*91f16700Schasinglulu * Return: Returns status, either success or error+reason. 1806*91f16700Schasinglulu * 1807*91f16700Schasinglulu */ 1808*91f16700Schasinglulu enum pm_ret_status pm_efuse_access(uint32_t address_high, 1809*91f16700Schasinglulu uint32_t address_low, 1810*91f16700Schasinglulu uint32_t *value) 1811*91f16700Schasinglulu { 1812*91f16700Schasinglulu uint32_t payload[PAYLOAD_ARG_CNT]; 1813*91f16700Schasinglulu 1814*91f16700Schasinglulu /* Send request to the PMU */ 1815*91f16700Schasinglulu PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low); 1816*91f16700Schasinglulu 1817*91f16700Schasinglulu return pm_ipi_send_sync(primary_proc, payload, value, 1); 1818*91f16700Schasinglulu } 1819