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