1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2023, STMicroelectronics 4 */ 5 6 #include <assert.h> 7 #include <compiler.h> 8 #include <config.h> 9 #include <drivers/regulator.h> 10 #include <initcall.h> 11 #include <keep.h> 12 #include <kernel/boot.h> 13 #include <kernel/delay.h> 14 #include <kernel/mutex.h> 15 #include <kernel/panic.h> 16 #include <kernel/pm.h> 17 #include <kernel/tee_time.h> 18 #include <kernel/thread.h> 19 #include <libfdt.h> 20 #include <limits.h> 21 #include <stdint.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <util.h> 25 26 static SLIST_HEAD(, regulator) regulator_device_list = 27 SLIST_HEAD_INITIALIZER(regulator); 28 29 static void lock_regulator(struct regulator *regulator) 30 { 31 /* 32 * Regulator operation may occur at runtime and during specific 33 * system power transition: power off, PM suspend and resume. 34 * These operate upon fastcall entries, under PSCI services 35 * execution, where non-secure world is not operational. In these 36 * cases we cannot take a mutex and will expect the mutex is 37 * unlocked. 38 */ 39 if (thread_get_id_may_fail() == THREAD_ID_INVALID) { 40 assert(!regulator->lock.state); 41 return; 42 } 43 44 mutex_lock(®ulator->lock); 45 } 46 47 static void unlock_regulator(struct regulator *regulator) 48 { 49 if (thread_get_id_may_fail() == THREAD_ID_INVALID) { 50 /* Path for PM sequences when with local Monitor */ 51 return; 52 } 53 54 mutex_unlock(®ulator->lock); 55 } 56 57 static TEE_Result set_state(struct regulator *regulator, bool on_not_off) 58 { 59 if (!regulator->ops->set_state) 60 return TEE_SUCCESS; 61 62 return regulator->ops->set_state(regulator, on_not_off); 63 } 64 65 static TEE_Result regulator_refcnt_enable(struct regulator *regulator) 66 { 67 TEE_Result res = TEE_ERROR_GENERIC; 68 69 FMSG("%s", regulator_name(regulator)); 70 71 if (regulator->supply) { 72 res = regulator_enable(regulator->supply); 73 if (res) 74 return res; 75 } 76 77 lock_regulator(regulator); 78 79 if (!regulator->refcount) { 80 res = set_state(regulator, true); 81 if (res) { 82 EMSG("regul %s set state failed with %#"PRIx32, 83 regulator_name(regulator), res); 84 85 unlock_regulator(regulator); 86 87 if (regulator->supply && 88 regulator_disable(regulator->supply)) 89 panic(); 90 91 return res; 92 } 93 } 94 95 regulator->refcount++; 96 if (!regulator->refcount) 97 panic(); 98 99 FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); 100 101 unlock_regulator(regulator); 102 103 return TEE_SUCCESS; 104 } 105 106 TEE_Result regulator_enable(struct regulator *regulator) 107 { 108 assert(regulator); 109 FMSG("%s", regulator_name(regulator)); 110 111 return regulator_refcnt_enable(regulator); 112 } 113 114 static TEE_Result regulator_refcnt_disable(struct regulator *regulator) 115 { 116 FMSG("%s", regulator_name(regulator)); 117 118 lock_regulator(regulator); 119 120 if (regulator->refcount == 1) { 121 TEE_Result res = set_state(regulator, false); 122 123 if (res) { 124 EMSG("regul %s set state failed with %#"PRIx32, 125 regulator_name(regulator), res); 126 unlock_regulator(regulator); 127 return res; 128 } 129 } 130 131 if (!regulator->refcount) { 132 EMSG("Unbalanced %s", regulator_name(regulator)); 133 panic(); 134 } 135 136 regulator->refcount--; 137 138 FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); 139 140 unlock_regulator(regulator); 141 142 if (regulator->supply && regulator_disable(regulator->supply)) { 143 /* We can't leave this unbalanced */ 144 EMSG("Can't disable %s", regulator_name(regulator->supply)); 145 panic(); 146 } 147 148 return TEE_SUCCESS; 149 } 150 151 TEE_Result regulator_disable(struct regulator *regulator) 152 { 153 assert(regulator); 154 FMSG("%s", regulator_name(regulator)); 155 156 return regulator_refcnt_disable(regulator); 157 } 158 159 bool regulator_is_enabled(struct regulator *regulator) 160 { 161 TEE_Result res = TEE_SUCCESS; 162 bool enabled = false; 163 164 if (!regulator->ops->get_state) 165 return true; 166 167 lock_regulator(regulator); 168 res = regulator->ops->get_state(regulator, &enabled); 169 unlock_regulator(regulator); 170 171 if (res) 172 EMSG("regul %s get state failed with %#"PRIx32, 173 regulator_name(regulator), res); 174 175 return !res && enabled; 176 } 177 178 TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv) 179 { 180 TEE_Result res = TEE_ERROR_GENERIC; 181 182 assert(regulator); 183 FMSG("%s %duV", regulator_name(regulator), level_uv); 184 185 if (level_uv < regulator->min_uv || level_uv > regulator->max_uv) 186 return TEE_ERROR_BAD_PARAMETERS; 187 188 if (level_uv == regulator->cur_uv) 189 return TEE_SUCCESS; 190 191 if (!regulator->ops->set_voltage) 192 return TEE_ERROR_NOT_SUPPORTED; 193 194 lock_regulator(regulator); 195 res = regulator->ops->set_voltage(regulator, level_uv); 196 unlock_regulator(regulator); 197 198 if (res) { 199 EMSG("regul %s set volt failed with %#"PRIx32, 200 regulator_name(regulator), res); 201 return res; 202 } 203 204 regulator->cur_uv = level_uv; 205 206 return TEE_SUCCESS; 207 } 208 209 TEE_Result regulator_register(struct regulator *regulator) 210 { 211 TEE_Result res = TEE_SUCCESS; 212 int min_uv = 0; 213 int max_uv = 0; 214 int uv = 0; 215 216 if (!regulator || !regulator->ops) 217 return TEE_ERROR_BAD_PARAMETERS; 218 219 regulator_get_range(regulator, &min_uv, &max_uv); 220 if (min_uv > max_uv) 221 return TEE_ERROR_BAD_PARAMETERS; 222 223 /* Sanitize regulator effective level */ 224 if (regulator->ops->get_voltage) { 225 res = regulator->ops->get_voltage(regulator, &uv); 226 if (res) 227 return res; 228 } else { 229 uv = min_uv; 230 } 231 regulator->cur_uv = uv; 232 233 if (uv < min_uv || uv > max_uv) { 234 res = regulator_set_voltage(regulator, min_uv); 235 if (res) 236 return res; 237 } 238 239 SLIST_INSERT_HEAD(®ulator_device_list, regulator, link); 240 241 return TEE_SUCCESS; 242 } 243 244 /* 245 * Log regulators state 246 */ 247 void regulator_print_state(const char *message __maybe_unused) 248 { 249 struct regulator *regulator = NULL; 250 251 DMSG("Regulator state: %s", message); 252 DMSG("name use\ten\tuV\tmin\tmax\tsupply"); 253 254 SLIST_FOREACH(regulator, ®ulator_device_list, link) 255 DMSG("%8s %u\t%d\t%d\t%d\t%d\t%s\n", 256 regulator->name, regulator->refcount, 257 regulator_is_enabled(regulator), 258 regulator_get_voltage(regulator), 259 regulator->min_uv, regulator->max_uv, 260 regulator->supply ? regulator_name(regulator->supply) : 261 "<none>"); 262 } 263 264 /* 265 * Clean-up regulators that are not used. 266 */ 267 static TEE_Result regulator_core_cleanup(void) 268 { 269 struct regulator *regulator = NULL; 270 271 SLIST_FOREACH(regulator, ®ulator_device_list, link) { 272 if (!regulator->refcount) { 273 DMSG("disable %s", regulator_name(regulator)); 274 lock_regulator(regulator); 275 set_state(regulator, false /* disable */); 276 unlock_regulator(regulator); 277 } 278 } 279 280 regulator_print_state(__func__); 281 282 return TEE_SUCCESS; 283 } 284 285 release_init_resource(regulator_core_cleanup); 286