xref: /optee_os/core/drivers/regulator/regulator.c (revision 23f867d38149c501891c441213b4d9f5ee9ee94e)
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(&regulator->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(&regulator->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 	if (regulator_is_always_on(regulator))
112 		return TEE_SUCCESS;
113 
114 	return regulator_refcnt_enable(regulator);
115 }
116 
117 static TEE_Result regulator_refcnt_disable(struct regulator *regulator)
118 {
119 	FMSG("%s", regulator_name(regulator));
120 
121 	lock_regulator(regulator);
122 
123 	if (regulator->refcount == 1) {
124 		TEE_Result res = set_state(regulator, false);
125 
126 		if (res) {
127 			EMSG("regul %s set state failed with %#"PRIx32,
128 			     regulator_name(regulator), res);
129 			unlock_regulator(regulator);
130 			return res;
131 		}
132 	}
133 
134 	if (!regulator->refcount) {
135 		EMSG("Unbalanced %s", regulator_name(regulator));
136 		panic();
137 	}
138 
139 	regulator->refcount--;
140 
141 	FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount);
142 
143 	unlock_regulator(regulator);
144 
145 	if (regulator->supply && regulator_disable(regulator->supply)) {
146 		/* We can't leave this unbalanced */
147 		EMSG("Can't disable %s", regulator_name(regulator->supply));
148 		panic();
149 	}
150 
151 	return TEE_SUCCESS;
152 }
153 
154 TEE_Result regulator_disable(struct regulator *regulator)
155 {
156 	assert(regulator);
157 	FMSG("%s", regulator_name(regulator));
158 
159 	if (regulator_is_always_on(regulator))
160 		return TEE_SUCCESS;
161 
162 	return regulator_refcnt_disable(regulator);
163 }
164 
165 bool regulator_is_enabled(struct regulator *regulator)
166 {
167 	TEE_Result res = TEE_SUCCESS;
168 	bool enabled = false;
169 
170 	if (!regulator->ops->get_state)
171 		return true;
172 
173 	lock_regulator(regulator);
174 	res = regulator->ops->get_state(regulator, &enabled);
175 	unlock_regulator(regulator);
176 
177 	if (res)
178 		EMSG("regul %s get state failed with %#"PRIx32,
179 		     regulator_name(regulator), res);
180 
181 	return !res && enabled;
182 }
183 
184 int regulator_get_voltage(struct regulator *regulator)
185 {
186 	TEE_Result res = TEE_SUCCESS;
187 	int level_uv = regulator->min_uv;
188 
189 	if (regulator->ops->get_voltage) {
190 		res = regulator->ops->get_voltage(regulator, &level_uv);
191 		if (res) {
192 			EMSG("%s get_voltage failed with %#"PRIx32,
193 			     regulator_name(regulator), res);
194 			level_uv = 0;
195 		}
196 	}
197 
198 	return level_uv;
199 }
200 
201 TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv)
202 {
203 	TEE_Result res = TEE_ERROR_GENERIC;
204 	int cur_uv = 0;
205 
206 	assert(regulator);
207 	FMSG("%s %duV", regulator_name(regulator), level_uv);
208 
209 	if (level_uv < regulator->min_uv || level_uv > regulator->max_uv)
210 		return TEE_ERROR_BAD_PARAMETERS;
211 
212 	cur_uv = regulator_get_voltage(regulator);
213 	if (level_uv == cur_uv)
214 		return TEE_SUCCESS;
215 
216 	if (!regulator->ops->set_voltage)
217 		return TEE_ERROR_NOT_SUPPORTED;
218 
219 	lock_regulator(regulator);
220 	res = regulator->ops->set_voltage(regulator, level_uv);
221 	unlock_regulator(regulator);
222 
223 	if (res) {
224 		EMSG("regul %s set volt failed with %#"PRIx32,
225 		     regulator_name(regulator), res);
226 		return res;
227 	}
228 
229 	return TEE_SUCCESS;
230 }
231 
232 TEE_Result regulator_supported_voltages(struct regulator *regulator,
233 					struct regulator_voltages_desc **desc,
234 					const int **levels)
235 {
236 	assert(regulator && desc && levels);
237 
238 	if (regulator->ops->supported_voltages) {
239 		TEE_Result res = TEE_ERROR_GENERIC;
240 
241 		res = regulator->ops->supported_voltages(regulator, desc,
242 							 levels);
243 		if (res != TEE_ERROR_NOT_SUPPORTED)
244 			return res;
245 	} else {
246 		*desc = &regulator->voltages_fallback.desc;
247 		*levels = regulator->voltages_fallback.levels;
248 	}
249 
250 	assert(((*desc)->type == VOLTAGE_TYPE_FULL_LIST &&
251 		(*levels)[0] >= regulator->min_uv && (*desc)->num_levels &&
252 		(*levels)[(*desc)->num_levels - 1] <= regulator->max_uv) ||
253 	       ((*desc)->type == VOLTAGE_TYPE_INCREMENT &&
254 		(*levels)[0] >= regulator->min_uv &&
255 		(*levels)[1] <= regulator->max_uv));
256 
257 	return TEE_SUCCESS;
258 }
259 
260 TEE_Result regulator_register(struct regulator *regulator)
261 {
262 	TEE_Result res = TEE_SUCCESS;
263 	int min_uv = 0;
264 	int max_uv = 0;
265 	int uv = 0;
266 
267 	if (!regulator || !regulator->ops ||
268 	    regulator->flags & ~REGULATOR_FLAGS_MASK)
269 		return TEE_ERROR_BAD_PARAMETERS;
270 
271 	regulator_get_range(regulator, &min_uv, &max_uv);
272 	if (min_uv > max_uv)
273 		return TEE_ERROR_BAD_PARAMETERS;
274 
275 	/* Sanitize regulator effective level */
276 	uv = regulator_get_voltage(regulator);
277 
278 	if (uv < min_uv || uv > max_uv) {
279 		res = regulator_set_voltage(regulator, min_uv);
280 		if (res)
281 			return res;
282 	}
283 
284 	/* Unbalanced enable refcount to keep always-on regulators enabled */
285 	if (regulator_is_always_on(regulator)) {
286 		res = regulator_refcnt_enable(regulator);
287 		if (res)
288 			return res;
289 	}
290 
291 	/* Preset voltage list in case ops::supported_voltages is NULL */
292 	if (regulator->min_uv == regulator->max_uv) {
293 		regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_FULL_LIST;
294 		regulator->voltages_fallback.desc.num_levels = 1;
295 		regulator->voltages_fallback.levels[0] = regulator->min_uv;
296 	} else {
297 		regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_INCREMENT;
298 		regulator->voltages_fallback.levels[0] = regulator->min_uv;
299 		regulator->voltages_fallback.levels[1] = regulator->max_uv;
300 		regulator->voltages_fallback.levels[2] = 1;
301 	}
302 
303 	SLIST_INSERT_HEAD(&regulator_device_list, regulator, link);
304 
305 	return TEE_SUCCESS;
306 }
307 
308 /*
309  * Clean-up regulators that are not used.
310  */
311 static TEE_Result regulator_core_cleanup(void)
312 {
313 	struct regulator *regulator = NULL;
314 
315 	SLIST_FOREACH(regulator, &regulator_device_list, link) {
316 		if (!regulator->refcount) {
317 			DMSG("disable %s", regulator_name(regulator));
318 			lock_regulator(regulator);
319 			set_state(regulator, false /* disable */);
320 			unlock_regulator(regulator);
321 		}
322 	}
323 
324 	regulator_print_tree();
325 
326 	return TEE_SUCCESS;
327 }
328 
329 release_init_resource(regulator_core_cleanup);
330 
331 /* Return updated message buffer position of NULL on failure */
332 static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...)
333 {
334 	va_list ap = { };
335 	int max_len = end - cur;
336 	int ret = 0;
337 
338 	va_start(ap, fmt);
339 	ret = vsnprintf(cur, max_len, fmt, ap);
340 	va_end(ap);
341 
342 	if (ret < 0 || ret >= max_len)
343 		return NULL;
344 
345 	return cur + ret;
346 }
347 
348 static struct regulator *find_next_regulator(struct regulator *parent,
349 					     struct regulator *sibling)
350 {
351 	struct regulator *regulator = NULL;
352 
353 	if (sibling)
354 		regulator = SLIST_NEXT(sibling, link);
355 	else
356 		regulator = SLIST_FIRST(&regulator_device_list);
357 
358 	while (regulator && regulator->supply != parent)
359 		regulator = SLIST_NEXT(regulator, link);
360 
361 	return regulator;
362 }
363 
364 /* Regulator is the last supplied one by its supply in the registered list */
365 static bool regulator_is_supply_last_supplied(struct regulator *regulator)
366 {
367 	return !find_next_regulator(regulator->supply, regulator);
368 }
369 
370 /* Supply last node may already be printed for indentation level @cur_indent */
371 static bool indent_with_empty_string(struct regulator *node_regulator,
372 				     int node_indent, int cur_indent)
373 {
374 	struct regulator *r = node_regulator;
375 	int n = 0;
376 
377 	/* Find supply at indentation level @node_indent - @cur_indent - 1 */
378 	for (n = 0; n < node_indent - cur_indent - 1; n++)
379 		r = r->supply;
380 
381 	return regulator_is_supply_last_supplied(r);
382 }
383 
384 static void __maybe_unused print_regulator(struct regulator *regulator,
385 					   int indent)
386 {
387 	static const char * const level_unit[] = { "uV", "mV", "V" };
388 	int max_unit = ARRAY_SIZE(level_unit);
389 	int level_max = 0;
390 	int level_min = 0;
391 	int level_cur = 0;
392 	char msg_buf[128] = { };
393 	char *msg_end = msg_buf + sizeof(msg_buf);
394 	char *msg = msg_buf;
395 	int n_max = 0;
396 	int n_min = 0;
397 	int n_cur = 0;
398 	int n = 0;
399 
400 	if (indent) {
401 		/* Indent for root clock level */
402 		msg = add_msg(msg, msg_end, "   ");
403 		if (!msg)
404 			goto out;
405 
406 		/* Indent for root supply to regulator supply levels */
407 		for (n = 0; n < indent - 1; n++) {
408 			if (indent_with_empty_string(regulator, indent, n))
409 				msg = add_msg(msg, msg_end, "    ");
410 			else
411 				msg = add_msg(msg, msg_end, "|   ");
412 			if (!msg)
413 				goto out;
414 		}
415 
416 		/* Regulator indentation */
417 		if (regulator_is_supply_last_supplied(regulator))
418 			msg = add_msg(msg, msg_end, "`-- ");
419 		else
420 			msg = add_msg(msg, msg_end, "|-- ");
421 
422 		if (!msg)
423 			goto out;
424 	} else {
425 		/* Root supply indentation */
426 		msg = add_msg(msg, msg_end, "o- ");
427 	}
428 
429 	regulator_get_range(regulator, &level_min, &level_max);
430 	level_cur = regulator_get_voltage(regulator);
431 
432 	for (n_cur = 1; !(level_cur % 1000) && n_cur < max_unit; n_cur++)
433 		level_cur /= 1000;
434 	for (n_max = 1; !(level_max % 1000) && n_max < max_unit; n_max++)
435 		level_max /= 1000;
436 	for (n_min = 1; !(level_min % 1000) && n_min < max_unit; n_min++)
437 		level_min /= 1000;
438 
439 	msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / flags %#"PRIx32
440 		      " / %d %s ", regulator_name(regulator),
441 		      regulator_is_enabled(regulator) ? "on " : "off",
442 		      regulator->refcount, regulator->flags,
443 		      level_cur, level_unit[n_cur - 1]);
444 	if (!msg)
445 		goto out;
446 
447 	if (level_min == level_max)
448 		msg = add_msg(msg, msg_end, "fixed)");
449 	else if (level_max == INT_MAX)
450 		msg = add_msg(msg, msg_end, "[%d %s .. MAX])",
451 			      level_min, level_unit[n_min - 1]);
452 	else
453 		msg = add_msg(msg, msg_end, "[%d %s .. %d %s])",
454 			      level_min, level_unit[n_min - 1],
455 			      level_max, level_unit[n_max - 1]);
456 
457 out:
458 	if (!msg)
459 		snprintf(msg_end - 4, 4, "...");
460 
461 	DMSG("%s", msg_buf);
462 }
463 
464 static void print_tree(void)
465 {
466 	struct regulator *regulator = NULL;
467 	struct regulator *parent = NULL;
468 	struct regulator *next = NULL;
469 	int indent = -1;
470 
471 	while (true) {
472 		next = find_next_regulator(parent, regulator);
473 		if (next) {
474 			print_regulator(next, indent + 1);
475 			/* Enter the subtree of the next regulator */
476 			parent = next;
477 			indent++;
478 			regulator = NULL;
479 		} else {
480 			/*
481 			 * We've processed all children at this level.
482 			 * If parent is NULL we're at the top and are done.
483 			 */
484 			if (!parent)
485 				break;
486 			/*
487 			 * Move up one level to resume with the next
488 			 * regulator of the parent.
489 			 */
490 			regulator = parent;
491 			parent = regulator->supply;
492 			indent--;
493 		}
494 	}
495 }
496 
497 void regulator_print_tree(void)
498 {
499 	if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) &&
500 	    TRACE_LEVEL >= TRACE_DEBUG) {
501 		DMSG("Regulator tree summary");
502 		if (SLIST_EMPTY(&regulator_device_list))
503 			DMSG("-- No registered regulator");
504 		else
505 			print_tree();
506 	}
507 }
508