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