1 /*
2 * Copyright (c) 2019-2020 Peter Bigot Consulting, LLC
3 * Copyright (c) 2021 NXP
4 * Copyright (c) 2022 Nordic Semiconductor ASA
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_DRIVERS_REGULATOR_H_
9 #define ZEPHYR_INCLUDE_DRIVERS_REGULATOR_H_
10
11 /**
12 * @brief Regulator Interface
13 * @defgroup regulator_interface Regulator Interface
14 * @ingroup io_interfaces
15 * @{
16 */
17
18 #include <errno.h>
19 #include <stdint.h>
20
21 #include <zephyr/device.h>
22 #include <zephyr/devicetree.h>
23 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
24 #include <zephyr/kernel.h>
25 #endif
26 #include <zephyr/sys/util_macro.h>
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 /** Opaque type to store regulator DVS states */
33 typedef uint8_t regulator_dvs_state_t;
34
35 /** Opaque type to store regulator modes */
36 typedef uint8_t regulator_mode_t;
37
38 /** Opaque bit map for regulator error flags (see @ref REGULATOR_ERRORS) */
39 typedef uint8_t regulator_error_flags_t;
40
41 /**
42 * @name Regulator error flags.
43 * @anchor REGULATOR_ERRORS
44 * @{
45 */
46
47 /** Voltage is too high. */
48 #define REGULATOR_ERROR_OVER_VOLTAGE BIT(0)
49 /** Current is too high. */
50 #define REGULATOR_ERROR_OVER_CURRENT BIT(1)
51 /** Temperature is too high. */
52 #define REGULATOR_ERROR_OVER_TEMP BIT(2)
53
54 /** @} */
55
56 /** @cond INTERNAL_HIDDEN */
57
58 typedef int (*regulator_dvs_state_set_t)(const struct device *dev,
59 regulator_dvs_state_t state);
60
61 /** @brief Driver-specific API functions to support parent regulator control. */
62 __subsystem struct regulator_parent_driver_api {
63 regulator_dvs_state_set_t dvs_state_set;
64 };
65
66 typedef int (*regulator_enable_t)(const struct device *dev);
67 typedef int (*regulator_disable_t)(const struct device *dev);
68 typedef unsigned int (*regulator_count_voltages_t)(const struct device *dev);
69 typedef int (*regulator_list_voltage_t)(const struct device *dev,
70 unsigned int idx, int32_t *volt_uv);
71 typedef int (*regulator_set_voltage_t)(const struct device *dev, int32_t min_uv,
72 int32_t max_uv);
73 typedef int (*regulator_get_voltage_t)(const struct device *dev,
74 int32_t *volt_uv);
75 typedef int (*regulator_set_current_limit_t)(const struct device *dev,
76 int32_t min_ua, int32_t max_ua);
77 typedef int (*regulator_get_current_limit_t)(const struct device *dev,
78 int32_t *curr_ua);
79 typedef int (*regulator_set_mode_t)(const struct device *dev,
80 regulator_mode_t mode);
81 typedef int (*regulator_get_mode_t)(const struct device *dev,
82 regulator_mode_t *mode);
83 typedef int (*regulator_get_error_flags_t)(
84 const struct device *dev, regulator_error_flags_t *flags);
85
86 /** @brief Driver-specific API functions to support regulator control. */
87 __subsystem struct regulator_driver_api {
88 regulator_enable_t enable;
89 regulator_disable_t disable;
90 regulator_count_voltages_t count_voltages;
91 regulator_list_voltage_t list_voltage;
92 regulator_set_voltage_t set_voltage;
93 regulator_get_voltage_t get_voltage;
94 regulator_set_current_limit_t set_current_limit;
95 regulator_get_current_limit_t get_current_limit;
96 regulator_set_mode_t set_mode;
97 regulator_get_mode_t get_mode;
98 regulator_get_error_flags_t get_error_flags;
99 };
100
101 /**
102 * @name Regulator flags
103 * @anchor REGULATOR_FLAGS
104 * @{
105 */
106 /** Indicates regulator must stay always ON */
107 #define REGULATOR_ALWAYS_ON BIT(0)
108 /** Indicates regulator must be initialized ON */
109 #define REGULATOR_BOOT_ON BIT(1)
110 /** Indicates if regulator must be enabled when initialized */
111 #define REGULATOR_INIT_ENABLED (REGULATOR_ALWAYS_ON | REGULATOR_BOOT_ON)
112
113 /** @} */
114
115 /** Indicates initial mode is unknown/not specified */
116 #define REGULATOR_INITIAL_MODE_UNKNOWN UINT8_MAX
117
118 /**
119 * @brief Common regulator config.
120 *
121 * This structure **must** be placed first in the driver's config structure.
122 */
123 struct regulator_common_config {
124 /** Minimum allowed voltage, in microvolts. */
125 int32_t min_uv;
126 /** Maximum allowed voltage, in microvolts. */
127 int32_t max_uv;
128 /** Initial voltage, in microvolts. */
129 int32_t init_uv;
130 /** Minimum allowed current, in microamps. */
131 int32_t min_ua;
132 /** Maximum allowed current, in microamps. */
133 int32_t max_ua;
134 /** Allowed modes */
135 const regulator_mode_t *allowed_modes;
136 /** Number of allowed modes */
137 uint8_t allowed_modes_cnt;
138 /** Regulator initial mode */
139 regulator_mode_t initial_mode;
140 /** Flags (@reg REGULATOR_FLAGS). */
141 uint8_t flags;
142 };
143
144 /**
145 * @brief Initialize common driver config from devicetree.
146 *
147 * @param node_id Node identifier.
148 */
149 #define REGULATOR_DT_COMMON_CONFIG_INIT(node_id) \
150 { \
151 .min_uv = DT_PROP_OR(node_id, regulator_min_microvolt, \
152 INT32_MIN), \
153 .max_uv = DT_PROP_OR(node_id, regulator_max_microvolt, \
154 INT32_MAX), \
155 .init_uv = DT_PROP_OR(node_id, regulator_init_microvolt, \
156 INT32_MIN), \
157 .min_ua = DT_PROP_OR(node_id, regulator_min_microamp, \
158 INT32_MIN), \
159 .max_ua = DT_PROP_OR(node_id, regulator_max_microamp, \
160 INT32_MAX), \
161 .allowed_modes = (const regulator_mode_t []) \
162 DT_PROP_OR(node_id, regulator_allowed_modes, {}), \
163 .allowed_modes_cnt = \
164 DT_PROP_LEN_OR(node_id, regulator_allowed_modes, 0), \
165 .initial_mode = DT_PROP_OR(node_id, regulator_initial_mode, \
166 REGULATOR_INITIAL_MODE_UNKNOWN), \
167 .flags = ((DT_PROP_OR(node_id, regulator_always_on, 0U) * \
168 REGULATOR_ALWAYS_ON) | \
169 (DT_PROP_OR(node_id, regulator_boot_on, 0U) * \
170 REGULATOR_BOOT_ON)), \
171 }
172
173 /**
174 * @brief Initialize common driver config from devicetree instance.
175 *
176 * @param inst Instance.
177 */
178 #define REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst) \
179 REGULATOR_DT_COMMON_CONFIG_INIT(DT_DRV_INST(inst))
180
181 /**
182 * @brief Common regulator data.
183 *
184 * This structure **must** be placed first in the driver's data structure.
185 */
186 struct regulator_common_data {
187 #if defined(CONFIG_REGULATOR_THREAD_SAFE_REFCNT) || defined(__DOXYGEN__)
188 /** Lock (only if @kconfig{CONFIG_REGULATOR_THREAD_SAFE_REFCNT}=y) */
189 struct k_mutex lock;
190 #endif
191 /** Reference count */
192 int refcnt;
193 };
194
195 /**
196 * @brief Initialize common regulator data.
197 *
198 * This function **must** be called when driver is initialized.
199 *
200 * @param dev Regulator device instance.
201 */
202 void regulator_common_data_init(const struct device *dev);
203
204 /**
205 * @brief Common function to initialize the regulator at init time.
206 *
207 * This function needs to be called after drivers initialize the regulator. It
208 * will:
209 *
210 * - Automatically enable the regulator if it is set to `regulator-boot-on`
211 * or `regulator-always-on` and increase its usage count.
212 * - Configure the regulator mode if `regulator-initial-mode` is set.
213 * - Ensure regulator voltage is set to a valid range.
214 *
215 * Regulators that are enabled by default in hardware, must set @p is_enabled to
216 * `true`.
217 *
218 * @param dev Regulator device instance
219 * @param is_enabled Indicate if the regulator is enabled by default in
220 * hardware.
221 *
222 * @retval 0 If enabled successfully.
223 * @retval -errno Negative errno in case of failure.
224 */
225 int regulator_common_init(const struct device *dev, bool is_enabled);
226
227 /**
228 * @brief Check if regulator is expected to be enabled at init time.
229 *
230 * @param dev Regulator device instance
231 * @return true If regulator needs to be enabled at init time.
232 * @return false If regulator does not need to be enabled at init time.
233 */
regulator_common_is_init_enabled(const struct device * dev)234 static inline bool regulator_common_is_init_enabled(const struct device *dev)
235 {
236 const struct regulator_common_config *config =
237 (const struct regulator_common_config *)dev->config;
238
239 return (config->flags & REGULATOR_INIT_ENABLED) != 0U;
240 }
241
242 /** @endcond */
243
244 /**
245 * @brief Regulator Parent Interface
246 * @defgroup regulator_parent_interface Regulator Parent Interface
247 * @{
248 */
249
250 /**
251 * @brief Set a DVS state.
252 *
253 * Some PMICs feature DVS (Dynamic Voltage Scaling) by allowing to program the
254 * voltage level for multiple states. Such states may be automatically changed
255 * by hardware using GPIO pins. Certain MCUs even allow to automatically
256 * configure specific output pins when entering low-power modes so that PMIC
257 * state is changed without software intervention. This API can be used when
258 * state needs to be changed by software.
259 *
260 * @param dev Parent regulator device instance.
261 * @param state DVS state (vendor specific identifier).
262 *
263 * @retval 0 If successful.
264 * @retval -ENOTSUP If given state is not supported.
265 * @retval -EPERM If state can't be changed by software.
266 * @retval -ENOSYS If function is not implemented.
267 * @retval -errno In case of any other error.
268 */
regulator_parent_dvs_state_set(const struct device * dev,regulator_dvs_state_t state)269 static inline int regulator_parent_dvs_state_set(const struct device *dev,
270 regulator_dvs_state_t state)
271 {
272 const struct regulator_parent_driver_api *api =
273 (const struct regulator_parent_driver_api *)dev->api;
274
275 if (api->dvs_state_set == NULL) {
276 return -ENOSYS;
277 }
278
279 return api->dvs_state_set(dev, state);
280 }
281
282 /** @} */
283
284 /**
285 * @brief Enable a regulator.
286 *
287 * Reference-counted request that a regulator be turned on. A regulator is
288 * considered "on" when it has reached a stable/usable state. Regulators that
289 * are always on, or configured in devicetree with `regulator-always-on` will
290 * always stay enabled, and so this function will always succeed.
291 *
292 * @param dev Regulator device instance
293 *
294 * @retval 0 If regulator has been successfully enabled.
295 * @retval -errno Negative errno in case of failure.
296 */
297 int regulator_enable(const struct device *dev);
298
299 /**
300 * @brief Check if a regulator is enabled.
301 *
302 * @param dev Regulator device instance.
303 *
304 * @retval true If regulator is enabled.
305 * @retval false If regulator is disabled.
306 */
307 bool regulator_is_enabled(const struct device *dev);
308
309 /**
310 * @brief Disable a regulator.
311 *
312 * Release a regulator after a previous regulator_enable() completed
313 * successfully. Regulators that are always on, or configured in devicetree with
314 * `regulator-always-on` will always stay enabled, and so this function will
315 * always succeed.
316 *
317 * This must be invoked at most once for each successful regulator_enable().
318 *
319 * @param dev Regulator device instance.
320 *
321 * @retval 0 If regulator has been successfully disabled.
322 * @retval -errno Negative errno in case of failure.
323 */
324 int regulator_disable(const struct device *dev);
325
326 /**
327 * @brief Obtain the number of supported voltage levels.
328 *
329 * Each voltage level supported by a regulator gets an index, starting from
330 * zero. The total number of supported voltage levels can be used together with
331 * regulator_list_voltage() to list all supported voltage levels.
332 *
333 * @param dev Regulator device instance.
334 *
335 * @return Number of supported voltages.
336 */
regulator_count_voltages(const struct device * dev)337 static inline unsigned int regulator_count_voltages(const struct device *dev)
338 {
339 const struct regulator_driver_api *api =
340 (const struct regulator_driver_api *)dev->api;
341
342 if (api->count_voltages == NULL) {
343 return 0U;
344 }
345
346 return api->count_voltages(dev);
347 }
348
349 /**
350 * @brief Obtain the value of a voltage given an index.
351 *
352 * Each voltage level supported by a regulator gets an index, starting from
353 * zero. Together with regulator_count_voltages(), this function can be used
354 * to iterate over all supported voltages.
355 *
356 * @param dev Regulator device instance.
357 * @param idx Voltage index.
358 * @param[out] volt_uv Where voltage for the given @p index will be stored, in
359 * microvolts.
360 *
361 * @retval 0 If @p index corresponds to a supported voltage.
362 * @retval -EINVAL If @p index does not correspond to a supported voltage.
363 */
regulator_list_voltage(const struct device * dev,unsigned int idx,int32_t * volt_uv)364 static inline int regulator_list_voltage(const struct device *dev,
365 unsigned int idx, int32_t *volt_uv)
366 {
367 const struct regulator_driver_api *api =
368 (const struct regulator_driver_api *)dev->api;
369
370 if (api->list_voltage == NULL) {
371 return -EINVAL;
372 }
373
374 return api->list_voltage(dev, idx, volt_uv);
375 }
376
377 /**
378 * @brief Check if a voltage within a window is supported.
379 *
380 * @param dev Regulator device instance.
381 * @param min_uv Minimum voltage in microvolts.
382 * @param max_uv maximum voltage in microvolts.
383 *
384 * @retval true If voltage is supported.
385 * @retval false If voltage is not supported.
386 */
387 bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
388 int32_t max_uv);
389
390 /**
391 * @brief Set the output voltage.
392 *
393 * The output voltage will be configured to the closest supported output
394 * voltage. regulator_get_voltage() can be used to obtain the actual configured
395 * voltage. The voltage will be applied to the active or selected mode. Output
396 * voltage may be limited using `regulator-min-microvolt` and/or
397 * `regulator-max-microvolt` in devicetree.
398 *
399 * @param dev Regulator device instance.
400 * @param min_uv Minimum acceptable voltage in microvolts.
401 * @param max_uv Maximum acceptable voltage in microvolts.
402 *
403 * @retval 0 If successful.
404 * @retval -EINVAL If the given voltage window is not valid.
405 * @retval -ENOSYS If function is not implemented.
406 * @retval -errno In case of any other error.
407 */
408 int regulator_set_voltage(const struct device *dev, int32_t min_uv,
409 int32_t max_uv);
410
411 /**
412 * @brief Obtain output voltage.
413 *
414 * @param dev Regulator device instance.
415 * @param[out] volt_uv Where configured output voltage will be stored.
416 *
417 * @retval 0 If successful
418 * @retval -ENOSYS If function is not implemented.
419 * @retval -errno In case of any other error.
420 */
regulator_get_voltage(const struct device * dev,int32_t * volt_uv)421 static inline int regulator_get_voltage(const struct device *dev,
422 int32_t *volt_uv)
423 {
424 const struct regulator_driver_api *api =
425 (const struct regulator_driver_api *)dev->api;
426
427 if (api->get_voltage == NULL) {
428 return -ENOSYS;
429 }
430
431 return api->get_voltage(dev, volt_uv);
432 }
433
434 /**
435 * @brief Set output current limit.
436 *
437 * The output current limit will be configured to the closest supported output
438 * current limit. regulator_get_current_limit() can be used to obtain the actual
439 * configured current limit. Current may be limited using `current-min-microamp`
440 * and/or `current-max-microamp` in Devicetree.
441 *
442 * @param dev Regulator device instance.
443 * @param min_ua Minimum acceptable current limit in microamps.
444 * @param max_ua Maximum acceptable current limit in microamps.
445 *
446 * @retval 0 If successful.
447 * @retval -EINVAL If the given current limit window is not valid.
448 * @retval -ENOSYS If function is not implemented.
449 * @retval -errno In case of any other error.
450 */
451 int regulator_set_current_limit(const struct device *dev, int32_t min_ua,
452 int32_t max_ua);
453
454 /**
455 * @brief Get output current limit.
456 *
457 * @param dev Regulator device instance.
458 * @param[out] curr_ua Where output current limit will be stored.
459 *
460 * @retval 0 If successful.
461 * @retval -ENOSYS If function is not implemented.
462 * @retval -errno In case of any other error.
463 */
regulator_get_current_limit(const struct device * dev,int32_t * curr_ua)464 static inline int regulator_get_current_limit(const struct device *dev,
465 int32_t *curr_ua)
466 {
467 const struct regulator_driver_api *api =
468 (const struct regulator_driver_api *)dev->api;
469
470 if (api->get_current_limit == NULL) {
471 return -ENOSYS;
472 }
473
474 return api->get_current_limit(dev, curr_ua);
475 }
476
477 /**
478 * @brief Set mode.
479 *
480 * Regulators can support multiple modes in order to permit different voltage
481 * configuration or better power savings. This API will apply a mode for
482 * the regulator. Allowed modes may be limited using `regulator-allowed-modes`
483 * devicetree property.
484 *
485 * @param dev Regulator device instance.
486 * @param mode Mode to select for this regulator.
487 *
488 * @retval 0 If successful.
489 * @retval -ENOTSUP If mode is not supported.
490 * @retval -ENOSYS If function is not implemented.
491 * @retval -errno In case of any other error.
492 */
493 int regulator_set_mode(const struct device *dev, regulator_mode_t mode);
494
495 /**
496 * @brief Get mode.
497 *
498 * @param dev Regulator device instance.
499 * @param[out] mode Where mode will be stored.
500 *
501 * @retval 0 If successful.
502 * @retval -ENOSYS If function is not implemented.
503 * @retval -errno In case of any other error.
504 */
regulator_get_mode(const struct device * dev,regulator_mode_t * mode)505 static inline int regulator_get_mode(const struct device *dev,
506 regulator_mode_t *mode)
507 {
508 const struct regulator_driver_api *api =
509 (const struct regulator_driver_api *)dev->api;
510
511 if (api->get_mode == NULL) {
512 return -ENOSYS;
513 }
514
515 return api->get_mode(dev, mode);
516 }
517
518 /**
519 * @brief Get active error flags.
520 *
521 * @param dev Regulator device instance.
522 * @param[out] flags Where error flags will be stored.
523 *
524 * @retval 0 If successful.
525 * @retval -ENOSYS If function is not implemented.
526 * @retval -errno In case of any other error.
527 */
regulator_get_error_flags(const struct device * dev,regulator_error_flags_t * flags)528 static inline int regulator_get_error_flags(const struct device *dev,
529 regulator_error_flags_t *flags)
530 {
531 const struct regulator_driver_api *api =
532 (const struct regulator_driver_api *)dev->api;
533
534 if (api->get_error_flags == NULL) {
535 return -ENOSYS;
536 }
537
538 return api->get_error_flags(dev, flags);
539 }
540
541 #ifdef __cplusplus
542 }
543 #endif
544
545 /** @} */
546
547 #endif /* ZEPHYR_INCLUDE_DRIVERS_REGULATOR_H_ */
548