1*40e40cd2SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause 2*40e40cd2SJorge Ramirez-Ortiz /* 3*40e40cd2SJorge Ramirez-Ortiz * Copyright (C) 2022 Foundries.io Ltd 4*40e40cd2SJorge Ramirez-Ortiz * Jorge Ramirez-Ortiz <jorge@foundries.io> 5*40e40cd2SJorge Ramirez-Ortiz */ 6*40e40cd2SJorge Ramirez-Ortiz 7*40e40cd2SJorge Ramirez-Ortiz #include <arm.h> 8*40e40cd2SJorge Ramirez-Ortiz #include <drivers/versal_mbox.h> 9*40e40cd2SJorge Ramirez-Ortiz #include <drivers/versal_pm.h> 10*40e40cd2SJorge Ramirez-Ortiz #include <initcall.h> 11*40e40cd2SJorge Ramirez-Ortiz #include <kernel/cache_helpers.h> 12*40e40cd2SJorge Ramirez-Ortiz #include <kernel/delay.h> 13*40e40cd2SJorge Ramirez-Ortiz #include <kernel/panic.h> 14*40e40cd2SJorge Ramirez-Ortiz #include <kernel/thread.h> 15*40e40cd2SJorge Ramirez-Ortiz #include <mm/core_memprot.h> 16*40e40cd2SJorge Ramirez-Ortiz #include <string.h> 17*40e40cd2SJorge Ramirez-Ortiz #include <tee/cache.h> 18*40e40cd2SJorge Ramirez-Ortiz #include <tee_api_types.h> 19*40e40cd2SJorge Ramirez-Ortiz #include <utee_defines.h> 20*40e40cd2SJorge Ramirez-Ortiz 21*40e40cd2SJorge Ramirez-Ortiz /* VERSAL_SIP_UID: 2ab9e4ec-93b9-11e7-a019dfe0dbad0ae0 */ 22*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_UID_0 U(0xece4b92a) 23*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_UID_1 U(0xe711b993) 24*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_UID_2 U(0xe0df19a0) 25*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_UID_3 U(0xe00aaddb) 26*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_MAJOR 0 27*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_MINOR 1 28*40e40cd2SJorge Ramirez-Ortiz 29*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_SVC_VERSION 0x8200ff03 30*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_SVC_UID 0x8200ff01 31*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_SIP_SVC 0xc2000000 32*40e40cd2SJorge Ramirez-Ortiz 33*40e40cd2SJorge Ramirez-Ortiz #define PAYLOAD_ARG_CNT 8 34*40e40cd2SJorge Ramirez-Ortiz 35*40e40cd2SJorge Ramirez-Ortiz /* MBOX IPI */ 36*40e40cd2SJorge Ramirez-Ortiz #define PM_MODULE_SHIFT 8 37*40e40cd2SJorge Ramirez-Ortiz #define PM_MODULE 2 38*40e40cd2SJorge Ramirez-Ortiz #define PM_API_ID(x) ((PM_MODULE << PM_MODULE_SHIFT) | (x)) 39*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_PM_MAJOR 0 40*40e40cd2SJorge Ramirez-Ortiz #define VERSAL_PM_MINOR 1 41*40e40cd2SJorge Ramirez-Ortiz 42*40e40cd2SJorge Ramirez-Ortiz /* PM API ids */ 43*40e40cd2SJorge Ramirez-Ortiz #define PM_GET_API_VERSION 1 44*40e40cd2SJorge Ramirez-Ortiz #define PM_GET_DEVICE_STATUS 3 45*40e40cd2SJorge Ramirez-Ortiz #define PM_GET_OP_CHARACTERISTIC 4 46*40e40cd2SJorge Ramirez-Ortiz #define PM_REGISTER_NOTIFIER 5 47*40e40cd2SJorge Ramirez-Ortiz #define PM_REQ_SUSPEND 6 48*40e40cd2SJorge Ramirez-Ortiz #define PM_SELF_SUSPEND 7 49*40e40cd2SJorge Ramirez-Ortiz #define PM_FORCE_POWERDOWN 8 50*40e40cd2SJorge Ramirez-Ortiz #define PM_ABORT_SUSPEND 9 51*40e40cd2SJorge Ramirez-Ortiz #define PM_REQ_WAKEUP 10 52*40e40cd2SJorge Ramirez-Ortiz #define PM_SET_WAKEUP_SOURCE 11 53*40e40cd2SJorge Ramirez-Ortiz #define PM_SYSTEM_SHUTDOWN 12 54*40e40cd2SJorge Ramirez-Ortiz #define PM_REQUEST_DEVICE 13 55*40e40cd2SJorge Ramirez-Ortiz #define PM_RELEASE_DEVICE 14 56*40e40cd2SJorge Ramirez-Ortiz #define PM_SET_REQUIREMENT 15 57*40e40cd2SJorge Ramirez-Ortiz #define PM_SET_MAX_LATENCY 16 58*40e40cd2SJorge Ramirez-Ortiz #define PM_RESET_ASSERT 17 59*40e40cd2SJorge Ramirez-Ortiz #define PM_RESET_GET_STATUS 18 60*40e40cd2SJorge Ramirez-Ortiz #define PM_INIT_FINALIZE 21 61*40e40cd2SJorge Ramirez-Ortiz #define PM_GET_CHIPID 24 62*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_REQUEST 28 63*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_RELEASE 29 64*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_GET_FUNCTION 30 65*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_SET_FUNCTION 31 66*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_CONFIG_PARAM_GET 32 67*40e40cd2SJorge Ramirez-Ortiz #define PM_PINCTRL_CONFIG_PARAM_SET 33 68*40e40cd2SJorge Ramirez-Ortiz #define PM_IOCTL 34 69*40e40cd2SJorge Ramirez-Ortiz #define PM_QUERY_DATA 35 70*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_ENABLE 36 71*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_DISABLE 37 72*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_GETSTATE 38 73*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_SETDIVIDER 39 74*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_GETDIVIDER 40 75*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_SETRATE 41 76*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_GETRATE 42 77*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_SETPARENT 43 78*40e40cd2SJorge Ramirez-Ortiz #define PM_CLOCK_GETPARENT 44 79*40e40cd2SJorge Ramirez-Ortiz #define PM_PLL_SET_PARAMETER 48 80*40e40cd2SJorge Ramirez-Ortiz #define PM_PLL_GET_PARAMETER 49 81*40e40cd2SJorge Ramirez-Ortiz #define PM_PLL_SET_MODE 50 82*40e40cd2SJorge Ramirez-Ortiz #define PM_PLL_GET_MODE 51 83*40e40cd2SJorge Ramirez-Ortiz #define PM_FEATURE_CHECK 63 84*40e40cd2SJorge Ramirez-Ortiz 85*40e40cd2SJorge Ramirez-Ortiz /* Loader API id */ 86*40e40cd2SJorge Ramirez-Ortiz #define PM_LOAD_PDI 0x701 87*40e40cd2SJorge Ramirez-Ortiz 88*40e40cd2SJorge Ramirez-Ortiz /* PDI sources */ 89*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_JTAG 0x0 90*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_QSPI24 0x1 91*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_QSPI32 0x2 92*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_SD0 0x3 93*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_EMMC0 0x4 94*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_SD1 0x5 95*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_EMMC1 0x6 96*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_USB 0x7 97*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_OSPI 0x8 98*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_SBI 0x9 99*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_SMAP 0xA 100*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_PCIE 0xB 101*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_SD1_LS 0xE 102*40e40cd2SJorge Ramirez-Ortiz #define PDI_SRC_DDR 0xF 103*40e40cd2SJorge Ramirez-Ortiz 104*40e40cd2SJorge Ramirez-Ortiz struct versal_sip_payload { 105*40e40cd2SJorge Ramirez-Ortiz uint32_t data[PAYLOAD_ARG_CNT]; 106*40e40cd2SJorge Ramirez-Ortiz }; 107*40e40cd2SJorge Ramirez-Ortiz 108*40e40cd2SJorge Ramirez-Ortiz static uint32_t versal_sip_call(uint32_t smc_fid, uint32_t arg0, uint32_t arg1, 109*40e40cd2SJorge Ramirez-Ortiz uint32_t arg2, uint32_t arg3, 110*40e40cd2SJorge Ramirez-Ortiz struct versal_sip_payload *payload) 111*40e40cd2SJorge Ramirez-Ortiz { 112*40e40cd2SJorge Ramirez-Ortiz struct thread_smc_args args = { 113*40e40cd2SJorge Ramirez-Ortiz .a0 = smc_fid, 114*40e40cd2SJorge Ramirez-Ortiz .a1 = reg_pair_to_64(arg1, arg0), 115*40e40cd2SJorge Ramirez-Ortiz .a2 = reg_pair_to_64(arg3, arg2), 116*40e40cd2SJorge Ramirez-Ortiz }; 117*40e40cd2SJorge Ramirez-Ortiz 118*40e40cd2SJorge Ramirez-Ortiz thread_smccc(&args); 119*40e40cd2SJorge Ramirez-Ortiz 120*40e40cd2SJorge Ramirez-Ortiz if (payload) { 121*40e40cd2SJorge Ramirez-Ortiz reg_pair_from_64(args.a0, &payload->data[1], &payload->data[0]); 122*40e40cd2SJorge Ramirez-Ortiz reg_pair_from_64(args.a1, &payload->data[3], &payload->data[2]); 123*40e40cd2SJorge Ramirez-Ortiz reg_pair_from_64(args.a2, &payload->data[5], &payload->data[4]); 124*40e40cd2SJorge Ramirez-Ortiz reg_pair_from_64(args.a3, &payload->data[7], &payload->data[6]); 125*40e40cd2SJorge Ramirez-Ortiz } 126*40e40cd2SJorge Ramirez-Ortiz 127*40e40cd2SJorge Ramirez-Ortiz /* allow the PLM to output its debug information */ 128*40e40cd2SJorge Ramirez-Ortiz if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) 129*40e40cd2SJorge Ramirez-Ortiz mdelay(500); 130*40e40cd2SJorge Ramirez-Ortiz 131*40e40cd2SJorge Ramirez-Ortiz return args.a0; 132*40e40cd2SJorge Ramirez-Ortiz } 133*40e40cd2SJorge Ramirez-Ortiz 134*40e40cd2SJorge Ramirez-Ortiz /* SIP call to program the FPGA has been obsoleted, use the PLM */ 135*40e40cd2SJorge Ramirez-Ortiz TEE_Result versal_write_fpga(paddr_t pa) 136*40e40cd2SJorge Ramirez-Ortiz { 137*40e40cd2SJorge Ramirez-Ortiz struct ipi_cmd cmd = { }; 138*40e40cd2SJorge Ramirez-Ortiz 139*40e40cd2SJorge Ramirez-Ortiz cmd.data[0] = PM_LOAD_PDI; 140*40e40cd2SJorge Ramirez-Ortiz cmd.data[1] = PDI_SRC_DDR; 141*40e40cd2SJorge Ramirez-Ortiz reg_pair_from_64(pa, &cmd.data[2], &cmd.data[3]); 142*40e40cd2SJorge Ramirez-Ortiz 143*40e40cd2SJorge Ramirez-Ortiz if (versal_mbox_notify(&cmd, NULL, NULL)) 144*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 145*40e40cd2SJorge Ramirez-Ortiz 146*40e40cd2SJorge Ramirez-Ortiz return TEE_SUCCESS; 147*40e40cd2SJorge Ramirez-Ortiz } 148*40e40cd2SJorge Ramirez-Ortiz 149*40e40cd2SJorge Ramirez-Ortiz TEE_Result versal_soc_version(uint8_t *version) 150*40e40cd2SJorge Ramirez-Ortiz { 151*40e40cd2SJorge Ramirez-Ortiz struct versal_sip_payload p = { }; 152*40e40cd2SJorge Ramirez-Ortiz const uint32_t version_shift = 12; 153*40e40cd2SJorge Ramirez-Ortiz 154*40e40cd2SJorge Ramirez-Ortiz if (!version) 155*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 156*40e40cd2SJorge Ramirez-Ortiz 157*40e40cd2SJorge Ramirez-Ortiz if (versal_sip_call(VERSAL_SIP_SVC | PM_GET_CHIPID, 0, 0, 0, 0, &p)) 158*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 159*40e40cd2SJorge Ramirez-Ortiz 160*40e40cd2SJorge Ramirez-Ortiz *version = p.data[2] >> version_shift; 161*40e40cd2SJorge Ramirez-Ortiz 162*40e40cd2SJorge Ramirez-Ortiz return TEE_SUCCESS; 163*40e40cd2SJorge Ramirez-Ortiz } 164*40e40cd2SJorge Ramirez-Ortiz 165*40e40cd2SJorge Ramirez-Ortiz static bool uuid_is_versal_pm(void) 166*40e40cd2SJorge Ramirez-Ortiz { 167*40e40cd2SJorge Ramirez-Ortiz struct versal_sip_payload p = { }; 168*40e40cd2SJorge Ramirez-Ortiz 169*40e40cd2SJorge Ramirez-Ortiz versal_sip_call(VERSAL_SIP_SVC_UID, 0, 0, 0, 0, &p); 170*40e40cd2SJorge Ramirez-Ortiz 171*40e40cd2SJorge Ramirez-Ortiz if (p.data[0] == VERSAL_SIP_UID_0 && p.data[2] == VERSAL_SIP_UID_1 && 172*40e40cd2SJorge Ramirez-Ortiz p.data[4] == VERSAL_SIP_UID_2 && p.data[6] == VERSAL_SIP_UID_3) 173*40e40cd2SJorge Ramirez-Ortiz return true; 174*40e40cd2SJorge Ramirez-Ortiz 175*40e40cd2SJorge Ramirez-Ortiz return false; 176*40e40cd2SJorge Ramirez-Ortiz } 177*40e40cd2SJorge Ramirez-Ortiz 178*40e40cd2SJorge Ramirez-Ortiz static TEE_Result versal_check_pm_abi(void) 179*40e40cd2SJorge Ramirez-Ortiz { 180*40e40cd2SJorge Ramirez-Ortiz struct versal_sip_payload p = { }; 181*40e40cd2SJorge Ramirez-Ortiz struct ipi_cmd cmd = { }; 182*40e40cd2SJorge Ramirez-Ortiz struct ipi_cmd rsp = { }; 183*40e40cd2SJorge Ramirez-Ortiz unsigned int major = 0; 184*40e40cd2SJorge Ramirez-Ortiz unsigned int minor = 0; 185*40e40cd2SJorge Ramirez-Ortiz 186*40e40cd2SJorge Ramirez-Ortiz if (!uuid_is_versal_pm()) { 187*40e40cd2SJorge Ramirez-Ortiz EMSG("Invalid SiP Service"); 188*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 189*40e40cd2SJorge Ramirez-Ortiz } 190*40e40cd2SJorge Ramirez-Ortiz 191*40e40cd2SJorge Ramirez-Ortiz if (versal_sip_call(VERSAL_SIP_SVC_VERSION, 0, 0, 0, 0, &p)) 192*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 193*40e40cd2SJorge Ramirez-Ortiz 194*40e40cd2SJorge Ramirez-Ortiz major = p.data[0]; 195*40e40cd2SJorge Ramirez-Ortiz minor = p.data[2]; 196*40e40cd2SJorge Ramirez-Ortiz if (major != VERSAL_SIP_MAJOR || minor < VERSAL_SIP_MINOR) { 197*40e40cd2SJorge Ramirez-Ortiz EMSG("Invalid SiP version: Major %d, Minor %d", major, minor); 198*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 199*40e40cd2SJorge Ramirez-Ortiz } 200*40e40cd2SJorge Ramirez-Ortiz 201*40e40cd2SJorge Ramirez-Ortiz cmd.data[0] = PM_API_ID(PM_GET_API_VERSION); 202*40e40cd2SJorge Ramirez-Ortiz if (versal_mbox_notify(&cmd, &rsp, NULL)) 203*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 204*40e40cd2SJorge Ramirez-Ortiz 205*40e40cd2SJorge Ramirez-Ortiz major = rsp.data[1] & 0xFFFF; 206*40e40cd2SJorge Ramirez-Ortiz minor = rsp.data[1] >> 16; 207*40e40cd2SJorge Ramirez-Ortiz if (major != VERSAL_PM_MAJOR || minor < VERSAL_PM_MINOR) { 208*40e40cd2SJorge Ramirez-Ortiz EMSG("Invalid PM version: Major %d, Minor %d", major, minor); 209*40e40cd2SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 210*40e40cd2SJorge Ramirez-Ortiz } 211*40e40cd2SJorge Ramirez-Ortiz 212*40e40cd2SJorge Ramirez-Ortiz return TEE_SUCCESS; 213*40e40cd2SJorge Ramirez-Ortiz } 214*40e40cd2SJorge Ramirez-Ortiz 215*40e40cd2SJorge Ramirez-Ortiz early_init_late(versal_check_pm_abi); 216