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