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