1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2019 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <arch.h> 8*91f16700Schasinglulu #include <stdlib.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu #include <services/std_svc.h> 11*91f16700Schasinglulu #include <string.h> 12*91f16700Schasinglulu #include <platform_def.h> 13*91f16700Schasinglulu #include <common/debug.h> 14*91f16700Schasinglulu #include <common/runtime_svc.h> 15*91f16700Schasinglulu #include <imx_sip_svc.h> 16*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 17*91f16700Schasinglulu #include <lib/mmio.h> 18*91f16700Schasinglulu #include <sci/sci.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx) 21*91f16700Schasinglulu 22*91f16700Schasinglulu #ifdef PLAT_imx8qm 23*91f16700Schasinglulu static const int ap_cluster_index[PLATFORM_CLUSTER_COUNT] = { 24*91f16700Schasinglulu SC_R_A53, SC_R_A72, 25*91f16700Schasinglulu }; 26*91f16700Schasinglulu #endif 27*91f16700Schasinglulu 28*91f16700Schasinglulu static int imx_srtc_set_time(uint32_t year_mon, 29*91f16700Schasinglulu unsigned long day_hour, 30*91f16700Schasinglulu unsigned long min_sec) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu return sc_timer_set_rtc_time(ipc_handle, 33*91f16700Schasinglulu year_mon >> 16, year_mon & 0xffff, 34*91f16700Schasinglulu day_hour >> 16, day_hour & 0xffff, 35*91f16700Schasinglulu min_sec >> 16, min_sec & 0xffff); 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu int imx_srtc_handler(uint32_t smc_fid, 39*91f16700Schasinglulu void *handle, 40*91f16700Schasinglulu u_register_t x1, 41*91f16700Schasinglulu u_register_t x2, 42*91f16700Schasinglulu u_register_t x3, 43*91f16700Schasinglulu u_register_t x4) 44*91f16700Schasinglulu { 45*91f16700Schasinglulu int ret; 46*91f16700Schasinglulu 47*91f16700Schasinglulu switch (x1) { 48*91f16700Schasinglulu case IMX_SIP_SRTC_SET_TIME: 49*91f16700Schasinglulu ret = imx_srtc_set_time(x2, x3, x4); 50*91f16700Schasinglulu break; 51*91f16700Schasinglulu default: 52*91f16700Schasinglulu ret = SMC_UNK; 53*91f16700Schasinglulu } 54*91f16700Schasinglulu 55*91f16700Schasinglulu SMC_RET1(handle, ret); 56*91f16700Schasinglulu } 57*91f16700Schasinglulu 58*91f16700Schasinglulu static void imx_cpufreq_set_target(uint32_t cluster_id, unsigned long freq) 59*91f16700Schasinglulu { 60*91f16700Schasinglulu sc_pm_clock_rate_t rate = (sc_pm_clock_rate_t)freq; 61*91f16700Schasinglulu 62*91f16700Schasinglulu #ifdef PLAT_imx8qm 63*91f16700Schasinglulu sc_pm_set_clock_rate(ipc_handle, ap_cluster_index[cluster_id], SC_PM_CLK_CPU, &rate); 64*91f16700Schasinglulu #endif 65*91f16700Schasinglulu #ifdef PLAT_imx8qx 66*91f16700Schasinglulu sc_pm_set_clock_rate(ipc_handle, SC_R_A35, SC_PM_CLK_CPU, &rate); 67*91f16700Schasinglulu #endif 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu int imx_cpufreq_handler(uint32_t smc_fid, 71*91f16700Schasinglulu u_register_t x1, 72*91f16700Schasinglulu u_register_t x2, 73*91f16700Schasinglulu u_register_t x3) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu switch (x1) { 76*91f16700Schasinglulu case IMX_SIP_SET_CPUFREQ: 77*91f16700Schasinglulu imx_cpufreq_set_target(x2, x3); 78*91f16700Schasinglulu break; 79*91f16700Schasinglulu default: 80*91f16700Schasinglulu return SMC_UNK; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu return 0; 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu static bool wakeup_src_irqsteer; 87*91f16700Schasinglulu 88*91f16700Schasinglulu bool imx_is_wakeup_src_irqsteer(void) 89*91f16700Schasinglulu { 90*91f16700Schasinglulu return wakeup_src_irqsteer; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu int imx_wakeup_src_handler(uint32_t smc_fid, 94*91f16700Schasinglulu u_register_t x1, 95*91f16700Schasinglulu u_register_t x2, 96*91f16700Schasinglulu u_register_t x3) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu switch (x1) { 99*91f16700Schasinglulu case IMX_SIP_WAKEUP_SRC_IRQSTEER: 100*91f16700Schasinglulu wakeup_src_irqsteer = true; 101*91f16700Schasinglulu break; 102*91f16700Schasinglulu case IMX_SIP_WAKEUP_SRC_SCU: 103*91f16700Schasinglulu wakeup_src_irqsteer = false; 104*91f16700Schasinglulu break; 105*91f16700Schasinglulu default: 106*91f16700Schasinglulu return SMC_UNK; 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu return SMC_OK; 110*91f16700Schasinglulu } 111*91f16700Schasinglulu 112*91f16700Schasinglulu int imx_otp_handler(uint32_t smc_fid, 113*91f16700Schasinglulu void *handle, 114*91f16700Schasinglulu u_register_t x1, 115*91f16700Schasinglulu u_register_t x2) 116*91f16700Schasinglulu { 117*91f16700Schasinglulu int ret; 118*91f16700Schasinglulu uint32_t fuse; 119*91f16700Schasinglulu 120*91f16700Schasinglulu switch (smc_fid) { 121*91f16700Schasinglulu case IMX_SIP_OTP_READ: 122*91f16700Schasinglulu ret = sc_misc_otp_fuse_read(ipc_handle, x1, &fuse); 123*91f16700Schasinglulu SMC_RET2(handle, ret, fuse); 124*91f16700Schasinglulu break; 125*91f16700Schasinglulu case IMX_SIP_OTP_WRITE: 126*91f16700Schasinglulu ret = sc_misc_otp_fuse_write(ipc_handle, x1, x2); 127*91f16700Schasinglulu SMC_RET1(handle, ret); 128*91f16700Schasinglulu break; 129*91f16700Schasinglulu default: 130*91f16700Schasinglulu ret = SMC_UNK; 131*91f16700Schasinglulu SMC_RET1(handle, ret); 132*91f16700Schasinglulu break; 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu return ret; 136*91f16700Schasinglulu } 137*91f16700Schasinglulu 138*91f16700Schasinglulu int imx_misc_set_temp_handler(uint32_t smc_fid, 139*91f16700Schasinglulu u_register_t x1, 140*91f16700Schasinglulu u_register_t x2, 141*91f16700Schasinglulu u_register_t x3, 142*91f16700Schasinglulu u_register_t x4) 143*91f16700Schasinglulu { 144*91f16700Schasinglulu return sc_misc_set_temp(ipc_handle, x1, x2, x3, x4); 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu #endif /* defined(PLAT_imx8qm) || defined(PLAT_imx8qx) */ 148*91f16700Schasinglulu 149*91f16700Schasinglulu #if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) 150*91f16700Schasinglulu int imx_src_handler(uint32_t smc_fid, 151*91f16700Schasinglulu u_register_t x1, 152*91f16700Schasinglulu u_register_t x2, 153*91f16700Schasinglulu u_register_t x3, 154*91f16700Schasinglulu void *handle) 155*91f16700Schasinglulu { 156*91f16700Schasinglulu uint32_t val; 157*91f16700Schasinglulu 158*91f16700Schasinglulu switch (x1) { 159*91f16700Schasinglulu case IMX_SIP_SRC_SET_SECONDARY_BOOT: 160*91f16700Schasinglulu if (x2 != 0U) { 161*91f16700Schasinglulu mmio_setbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET, 162*91f16700Schasinglulu SRC_GPR10_PERSIST_SECONDARY_BOOT); 163*91f16700Schasinglulu } else { 164*91f16700Schasinglulu mmio_clrbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET, 165*91f16700Schasinglulu SRC_GPR10_PERSIST_SECONDARY_BOOT); 166*91f16700Schasinglulu } 167*91f16700Schasinglulu break; 168*91f16700Schasinglulu case IMX_SIP_SRC_IS_SECONDARY_BOOT: 169*91f16700Schasinglulu val = mmio_read_32(IMX_SRC_BASE + SRC_GPR10_OFFSET); 170*91f16700Schasinglulu return !!(val & SRC_GPR10_PERSIST_SECONDARY_BOOT); 171*91f16700Schasinglulu default: 172*91f16700Schasinglulu return SMC_UNK; 173*91f16700Schasinglulu 174*91f16700Schasinglulu }; 175*91f16700Schasinglulu 176*91f16700Schasinglulu return 0; 177*91f16700Schasinglulu } 178*91f16700Schasinglulu #endif /* defined(PLAT_imx8mm) || defined(PLAT_imx8mq) */ 179*91f16700Schasinglulu 180*91f16700Schasinglulu static uint64_t imx_get_commit_hash(u_register_t x2, 181*91f16700Schasinglulu u_register_t x3, 182*91f16700Schasinglulu u_register_t x4) 183*91f16700Schasinglulu { 184*91f16700Schasinglulu /* Parse the version_string */ 185*91f16700Schasinglulu char *parse = (char *)version_string; 186*91f16700Schasinglulu uint64_t hash = 0; 187*91f16700Schasinglulu 188*91f16700Schasinglulu do { 189*91f16700Schasinglulu parse = strchr(parse, '-'); 190*91f16700Schasinglulu if (parse) { 191*91f16700Schasinglulu parse += 1; 192*91f16700Schasinglulu if (*(parse) == 'g') { 193*91f16700Schasinglulu /* Default is 7 hexadecimal digits */ 194*91f16700Schasinglulu memcpy((void *)&hash, (void *)(parse + 1), 7); 195*91f16700Schasinglulu break; 196*91f16700Schasinglulu } 197*91f16700Schasinglulu } 198*91f16700Schasinglulu 199*91f16700Schasinglulu } while (parse != NULL); 200*91f16700Schasinglulu 201*91f16700Schasinglulu return hash; 202*91f16700Schasinglulu } 203*91f16700Schasinglulu 204*91f16700Schasinglulu uint64_t imx_buildinfo_handler(uint32_t smc_fid, 205*91f16700Schasinglulu u_register_t x1, 206*91f16700Schasinglulu u_register_t x2, 207*91f16700Schasinglulu u_register_t x3, 208*91f16700Schasinglulu u_register_t x4) 209*91f16700Schasinglulu { 210*91f16700Schasinglulu uint64_t ret; 211*91f16700Schasinglulu 212*91f16700Schasinglulu switch (x1) { 213*91f16700Schasinglulu case IMX_SIP_BUILDINFO_GET_COMMITHASH: 214*91f16700Schasinglulu ret = imx_get_commit_hash(x2, x3, x4); 215*91f16700Schasinglulu break; 216*91f16700Schasinglulu default: 217*91f16700Schasinglulu return SMC_UNK; 218*91f16700Schasinglulu } 219*91f16700Schasinglulu 220*91f16700Schasinglulu return ret; 221*91f16700Schasinglulu } 222*91f16700Schasinglulu 223*91f16700Schasinglulu int imx_kernel_entry_handler(uint32_t smc_fid, 224*91f16700Schasinglulu u_register_t x1, 225*91f16700Schasinglulu u_register_t x2, 226*91f16700Schasinglulu u_register_t x3, 227*91f16700Schasinglulu u_register_t x4) 228*91f16700Schasinglulu { 229*91f16700Schasinglulu static entry_point_info_t bl33_image_ep_info; 230*91f16700Schasinglulu entry_point_info_t *next_image_info; 231*91f16700Schasinglulu unsigned int mode; 232*91f16700Schasinglulu 233*91f16700Schasinglulu if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000)) 234*91f16700Schasinglulu return SMC_UNK; 235*91f16700Schasinglulu 236*91f16700Schasinglulu mode = MODE32_svc; 237*91f16700Schasinglulu 238*91f16700Schasinglulu next_image_info = &bl33_image_ep_info; 239*91f16700Schasinglulu 240*91f16700Schasinglulu next_image_info->pc = x1; 241*91f16700Schasinglulu 242*91f16700Schasinglulu next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE, 243*91f16700Schasinglulu (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)); 244*91f16700Schasinglulu 245*91f16700Schasinglulu next_image_info->args.arg0 = 0; 246*91f16700Schasinglulu next_image_info->args.arg1 = 0; 247*91f16700Schasinglulu next_image_info->args.arg2 = x3; 248*91f16700Schasinglulu 249*91f16700Schasinglulu SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); 250*91f16700Schasinglulu 251*91f16700Schasinglulu cm_init_my_context(next_image_info); 252*91f16700Schasinglulu cm_prepare_el3_exit(NON_SECURE); 253*91f16700Schasinglulu 254*91f16700Schasinglulu return 0; 255*91f16700Schasinglulu } 256