11a3d3273SEtienne Carriere /* SPDX-License-Identifier: BSD-2-Clause */
21a3d3273SEtienne Carriere /*
31a3d3273SEtienne Carriere * Copyright (c) 2023, STMicroelectronics
41a3d3273SEtienne Carriere */
5d50fee03SEtienne Carriere #ifndef __DRIVERS_REGULATOR_H
6d50fee03SEtienne Carriere #define __DRIVERS_REGULATOR_H
71a3d3273SEtienne Carriere
81a3d3273SEtienne Carriere #include <assert.h>
91a3d3273SEtienne Carriere #include <bitstring.h>
10c80790feSEtienne Carriere #include <kernel/mutex_pm_aware.h>
111a3d3273SEtienne Carriere #include <sys/queue.h>
121a3d3273SEtienne Carriere #include <tee_api_types.h>
131a3d3273SEtienne Carriere #include <stdbool.h>
141a3d3273SEtienne Carriere #include <stdint.h>
15e3830fc7SEtienne Carriere #include <util.h>
16e3830fc7SEtienne Carriere
17e3830fc7SEtienne Carriere /* Regulator property flags: related to device tree binding properties */
18e3830fc7SEtienne Carriere
19e3830fc7SEtienne Carriere /* Regulator should never be disabled. DT property: regulator-always-on */
20e3830fc7SEtienne Carriere #define REGULATOR_ALWAYS_ON BIT(0)
2166d7ea0eSEtienne Carriere /* Enables pull down mode. DT property: regulator-pull-down */
2266d7ea0eSEtienne Carriere #define REGULATOR_PULL_DOWN BIT(1)
23dc9540cbSEtienne Carriere /*
24dc9540cbSEtienne Carriere * It's expected that this regulator was left on by the bootloader.
25dc9540cbSEtienne Carriere * The core shouldn't prevent it from being turned off later.
26dc9540cbSEtienne Carriere * DT property: regulator-boot-on
27dc9540cbSEtienne Carriere */
28dc9540cbSEtienne Carriere #define REGULATOR_BOOT_ON BIT(2)
291dc11585SThomas Bourgoin /*
301dc11585SThomas Bourgoin * Enables over current protection.
311dc11585SThomas Bourgoin * DT property: regulator-over-current-protection
321dc11585SThomas Bourgoin */
331dc11585SThomas Bourgoin #define REGULATOR_OVER_CURRENT BIT(3)
34e3830fc7SEtienne Carriere
35dc9540cbSEtienne Carriere #define REGULATOR_FLAGS_MASK (REGULATOR_ALWAYS_ON | REGULATOR_PULL_DOWN | \
361dc11585SThomas Bourgoin REGULATOR_BOOT_ON | REGULATOR_OVER_CURRENT)
371a3d3273SEtienne Carriere
381a3d3273SEtienne Carriere struct regulator_ops;
391a3d3273SEtienne Carriere
401a3d3273SEtienne Carriere /*
416558b565SEtienne Carriere * struct regu_dt_desc - Regulator description passed to regulator_dt_register()
426558b565SEtienne Carriere * @priv: Regulator driver private data
436558b565SEtienne Carriere * @name: Regulator string name for debug purpose
446558b565SEtienne Carriere * @supply_name: Regulator supply name for node property *-supply or NULL
456558b565SEtienne Carriere * @ops: Operation handlers for the regulator
466558b565SEtienne Carriere * @regulator: Pointer to preallocated regulator or NULL if none
476558b565SEtienne Carriere */
486558b565SEtienne Carriere struct regu_dt_desc {
496558b565SEtienne Carriere void *priv;
50b69e72f2SEtienne Carriere const char *name;
516558b565SEtienne Carriere const char *supply_name;
526558b565SEtienne Carriere const struct regulator_ops *ops;
536558b565SEtienne Carriere struct regulator *regulator;
546558b565SEtienne Carriere };
556558b565SEtienne Carriere
566558b565SEtienne Carriere /*
5743c155baSEtienne Carriere * Defines the format of struct voltages::entries
5843c155baSEtienne Carriere *
5943c155baSEtienne Carriere * If regulator_voltages::type is VOLTAGE_TYPE_FULL_LIST, then
6043c155baSEtienne Carriere * regulator_voltages@entries stores regulator_voltages::num_levels cells,
6143c155baSEtienne Carriere * listing supported voltage levels in uV from lowest to highest value.
6243c155baSEtienne Carriere *
6343c155baSEtienne Carriere * If regulator_voltages::type is VOLTAGE_TYPE_INCREMENT, then
6443c155baSEtienne Carriere * regulator_voltages::entries stores 3 cells: min level, max level and
6543c155baSEtienne Carriere * level increment step, all in uV. When so, regulator_voltages::num_levels
6643c155baSEtienne Carriere * is meaningless.
6743c155baSEtienne Carriere */
6843c155baSEtienne Carriere enum voltage_type {
6943c155baSEtienne Carriere VOLTAGE_TYPE_INVALID = 0,
7043c155baSEtienne Carriere VOLTAGE_TYPE_FULL_LIST, /* extensive list in uV */
7143c155baSEtienne Carriere VOLTAGE_TYPE_INCREMENT /* min, max, increment (in uV) */
7243c155baSEtienne Carriere };
7343c155baSEtienne Carriere
7443c155baSEtienne Carriere /*
75ace929f0SEtienne Carriere * struct regulator_voltages_desc - Voltage levels description
7643c155baSEtienne Carriere * @type: Type of level description
77ace929f0SEtienne Carriere * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST
7843c155baSEtienne Carriere *
7943c155baSEtienne Carriere */
80ace929f0SEtienne Carriere struct regulator_voltages_desc {
8143c155baSEtienne Carriere enum voltage_type type;
8243c155baSEtienne Carriere size_t num_levels;
8343c155baSEtienne Carriere };
8443c155baSEtienne Carriere
8543c155baSEtienne Carriere /*
861a3d3273SEtienne Carriere * struct regulator - A regulator instance
871a3d3273SEtienne Carriere * @ops: Operation handlers for the regulator
881a3d3273SEtienne Carriere * @supply: Regulator supply reference or NULL if none
891a3d3273SEtienne Carriere * @priv: Regulator driver private data
901a3d3273SEtienne Carriere * @name: Regulator string name for debug purpose or NULL
911a3d3273SEtienne Carriere * @min_uv: Min possible voltage level in microvolt (uV)
921a3d3273SEtienne Carriere * @max_uv: Max possible voltage level in microvolt (uV)
938c48c11bSEtienne Carriere * @ramp_delay_uv_per_us: Voltage level change delay in uV/s
94*4e51bea9SEtienne Carriere * @enable_ramp_delay_us: Delay after enable, in microseconds (us)
95e3830fc7SEtienne Carriere * @flags: REGULATOR_* property flags
961a3d3273SEtienne Carriere * @refcount: Regulator enable request reference counter
97c80790feSEtienne Carriere * @mutex: Concurrent access protection considering PM context sequences
9843c155baSEtienne Carriere * @voltages_fallback: Default supported voltage range description
991a3d3273SEtienne Carriere * @link: Link in initialized regulator list
1001a3d3273SEtienne Carriere */
1011a3d3273SEtienne Carriere struct regulator {
1021a3d3273SEtienne Carriere /* Fields initialized by caller of regulator_register() */
1031a3d3273SEtienne Carriere const struct regulator_ops *ops;
1041a3d3273SEtienne Carriere struct regulator *supply;
1051a3d3273SEtienne Carriere void *priv;
1061a3d3273SEtienne Carriere char *name;
1071a3d3273SEtienne Carriere int min_uv;
1081a3d3273SEtienne Carriere int max_uv;
1098c48c11bSEtienne Carriere unsigned int ramp_delay_uv_per_us;
110*4e51bea9SEtienne Carriere unsigned int enable_ramp_delay_us;
1111a3d3273SEtienne Carriere /* Fields internal to regulator framework */
112e3830fc7SEtienne Carriere unsigned int flags;
1131a3d3273SEtienne Carriere unsigned int refcount;
114c80790feSEtienne Carriere struct mutex_pm_aware mutex;
11543c155baSEtienne Carriere struct voltages_fallback {
116ace929f0SEtienne Carriere struct regulator_voltages_desc desc;
11743c155baSEtienne Carriere int levels[3];
11843c155baSEtienne Carriere } voltages_fallback;
11943c155baSEtienne Carriere size_t levels_count_fallback;
1201a3d3273SEtienne Carriere SLIST_ENTRY(regulator) link;
1211a3d3273SEtienne Carriere };
1221a3d3273SEtienne Carriere
1231a3d3273SEtienne Carriere /*
1241a3d3273SEtienne Carriere * struct regulator_ops - Regulator operation handlers
1251a3d3273SEtienne Carriere *
1261a3d3273SEtienne Carriere * @set_state: Enable or disable a regulator
1271a3d3273SEtienne Carriere * @get_state: Get regulator effective state
1281a3d3273SEtienne Carriere * @set_voltage: Set voltage level in microvolt (uV)
1291a3d3273SEtienne Carriere * @get_voltage: Get current voltage in microvolt (uV)
13043c155baSEtienne Carriere * @supported_voltages: Get supported levels description
1316558b565SEtienne Carriere * @supplied_init: Optional, finalize initialization once supply is ready
1321a3d3273SEtienne Carriere */
1331a3d3273SEtienne Carriere struct regulator_ops {
1341a3d3273SEtienne Carriere TEE_Result (*set_state)(struct regulator *r, bool enabled);
1351a3d3273SEtienne Carriere TEE_Result (*get_state)(struct regulator *r, bool *enabled);
1361a3d3273SEtienne Carriere TEE_Result (*set_voltage)(struct regulator *r, int level_uv);
1371a3d3273SEtienne Carriere TEE_Result (*get_voltage)(struct regulator *r, int *level_uv);
13843c155baSEtienne Carriere TEE_Result (*supported_voltages)(struct regulator *r,
139ace929f0SEtienne Carriere struct regulator_voltages_desc **desc,
140ace929f0SEtienne Carriere const int **levels);
1416558b565SEtienne Carriere TEE_Result (*supplied_init)(struct regulator *r, const void *fdt,
1426558b565SEtienne Carriere int node);
1431a3d3273SEtienne Carriere };
1441a3d3273SEtienne Carriere
1451a3d3273SEtienne Carriere #ifdef CFG_DRIVERS_REGULATOR
1461a3d3273SEtienne Carriere /*
1471a3d3273SEtienne Carriere * regulator_enable() - Enable regulator
1481a3d3273SEtienne Carriere * @regulator: Regulator reference
1491a3d3273SEtienne Carriere */
1501a3d3273SEtienne Carriere TEE_Result regulator_enable(struct regulator *regulator);
1511a3d3273SEtienne Carriere
1521a3d3273SEtienne Carriere /*
1531a3d3273SEtienne Carriere * regulator_disable() - Disable regulator
1541a3d3273SEtienne Carriere * @regulator: Regulator reference
1551a3d3273SEtienne Carriere */
1561a3d3273SEtienne Carriere TEE_Result regulator_disable(struct regulator *regulator);
1571a3d3273SEtienne Carriere
1581a3d3273SEtienne Carriere /*
1591a3d3273SEtienne Carriere * regulator_is_enabled() - Return whether or not regulator is currently enabled
1601a3d3273SEtienne Carriere * despite its refcount value.
1611a3d3273SEtienne Carriere * @regulator: Regulator reference
1621a3d3273SEtienne Carriere */
1631a3d3273SEtienne Carriere bool regulator_is_enabled(struct regulator *regulator);
1641a3d3273SEtienne Carriere
1651a3d3273SEtienne Carriere /*
1661a3d3273SEtienne Carriere * regulator_set_voltage() - Set regulator to target level in microvolt
1671a3d3273SEtienne Carriere * @regulator: Regulator reference
1681a3d3273SEtienne Carriere * @level_uv: Level in microvolt
1691a3d3273SEtienne Carriere */
1701a3d3273SEtienne Carriere TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv);
1711a3d3273SEtienne Carriere
1721a3d3273SEtienne Carriere /*
1731a3d3273SEtienne Carriere * regulator_register() - Register and initialize a regulator
1741a3d3273SEtienne Carriere * @regulator: Regulator reference
1751a3d3273SEtienne Carriere */
1761a3d3273SEtienne Carriere TEE_Result regulator_register(struct regulator *regulator);
1771a3d3273SEtienne Carriere
1781a3d3273SEtienne Carriere /* Print registered regulators and their state to the output console */
1791a3d3273SEtienne Carriere void regulator_print_state(const char *message);
1801a3d3273SEtienne Carriere #else
regulator_enable(struct regulator * regulator __unused)1811a3d3273SEtienne Carriere static inline TEE_Result regulator_enable(struct regulator *regulator __unused)
1821a3d3273SEtienne Carriere {
1831a3d3273SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
1841a3d3273SEtienne Carriere }
1851a3d3273SEtienne Carriere
regulator_disable(struct regulator * regulator __unused)1861a3d3273SEtienne Carriere static inline TEE_Result regulator_disable(struct regulator *regulator __unused)
1871a3d3273SEtienne Carriere {
1881a3d3273SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
1891a3d3273SEtienne Carriere }
1901a3d3273SEtienne Carriere
regulator_is_enabled(struct regulator * regulator __unused)1911a3d3273SEtienne Carriere static inline bool regulator_is_enabled(struct regulator *regulator __unused)
1921a3d3273SEtienne Carriere {
1931a3d3273SEtienne Carriere return false;
1941a3d3273SEtienne Carriere }
1951a3d3273SEtienne Carriere
regulator_set_voltage(struct regulator * regul __unused,int level_mv __unused)1961a3d3273SEtienne Carriere static inline TEE_Result regulator_set_voltage(struct regulator *regul __unused,
1971a3d3273SEtienne Carriere int level_mv __unused)
1981a3d3273SEtienne Carriere {
1991a3d3273SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
2001a3d3273SEtienne Carriere }
2011a3d3273SEtienne Carriere
regulator_init(struct regulator * regulator __unused)2021a3d3273SEtienne Carriere static inline TEE_Result regulator_init(struct regulator *regulator __unused)
2031a3d3273SEtienne Carriere {
2041a3d3273SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
2051a3d3273SEtienne Carriere }
2061a3d3273SEtienne Carriere
regulator_print_state(const char * message __unused)2071a3d3273SEtienne Carriere static inline void regulator_print_state(const char *message __unused)
2081a3d3273SEtienne Carriere {
2091a3d3273SEtienne Carriere }
2101a3d3273SEtienne Carriere #endif /*CFG_DRIVERS_REGULATOR*/
2111a3d3273SEtienne Carriere
2126558b565SEtienne Carriere #if defined(CFG_DRIVERS_REGULATOR) && defined(CFG_DT)
2136558b565SEtienne Carriere /*
21486ea47daSEtienne Carriere * regulator_dt_get_supply() - Get a regulator supply from name and DT node
21586ea47daSEtienne Carriere * @fdt: FDT to work on
21686ea47daSEtienne Carriere * @node: DT node of the regulator consumer
21786ea47daSEtienne Carriere * @supply_name: Name of the supply in DT property xxx-supply
21886ea47daSEtienne Carriere * @regulator: Output regulator upon success
21986ea47daSEtienne Carriere *
22086ea47daSEtienne Carriere * Upon success, this function provides the pointer to regulator
22186ea47daSEtienne Carriere * defined by DT binding property @name-supply phandle reference.
22286ea47daSEtienne Carriere *
22386ea47daSEtienne Carriere * This function returns TEE_ERROR_DEFER_DRIVER_INIT if supply exists but is
22486ea47daSEtienne Carriere * not yet initialized.
22586ea47daSEtienne Carriere */
22686ea47daSEtienne Carriere TEE_Result regulator_dt_get_supply(const void *fdt, int node,
22786ea47daSEtienne Carriere const char *supply_name,
22886ea47daSEtienne Carriere struct regulator **regulator);
22986ea47daSEtienne Carriere
23086ea47daSEtienne Carriere /*
2316558b565SEtienne Carriere * regulator_dt_register() - Register a regulator to related to a DT node
2326558b565SEtienne Carriere * @fdt: FDT to work on
2336558b565SEtienne Carriere * @node: DT node of the regulator exposed by regulator driver
2346558b565SEtienne Carriere * @provider_node: Node where xxx-supply property is found or -1 if no supply.
2356558b565SEtienne Carriere * @desc: Description of the regulator to register
2366558b565SEtienne Carriere *
2376558b565SEtienne Carriere * This function registers and initializes a regulator instance once its supply
2386558b565SEtienne Carriere * if found, if any. Regulators registered with this function can be found by
2396558b565SEtienne Carriere * their consumer drivers using API function regulator_dt_get_supply() or like.
2406558b565SEtienne Carriere *
2416558b565SEtienne Carriere * Return TEE_SUCCESS in case of success
2426558b565SEtienne Carriere * Return TEE_ERROR_OUT_OF_MEMORY if failed on memory allocation
2436558b565SEtienne Carriere * Return any other TEE_Result compliant code in case of error
2446558b565SEtienne Carriere */
2456558b565SEtienne Carriere TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node,
2466558b565SEtienne Carriere const struct regu_dt_desc *desc);
2476558b565SEtienne Carriere #else
regulator_dt_get_supply(const void * fdt __unused,int node __unused,const char * supply __unused,struct regulator ** r __unused)2486558b565SEtienne Carriere static inline TEE_Result regulator_dt_get_supply(const void *fdt __unused,
2496558b565SEtienne Carriere int node __unused,
2506558b565SEtienne Carriere const char *supply __unused,
2516558b565SEtienne Carriere struct regulator **r __unused)
2526558b565SEtienne Carriere {
2536558b565SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
2546558b565SEtienne Carriere }
2556558b565SEtienne Carriere
2566558b565SEtienne Carriere static inline TEE_Result
regulator_dt_register(const void * fdt __unused,int node __unused,int provider_node __unused,const struct regu_dt_desc * d __unused)2576558b565SEtienne Carriere regulator_dt_register(const void *fdt __unused, int node __unused,
2586558b565SEtienne Carriere int provider_node __unused,
2596558b565SEtienne Carriere const struct regu_dt_desc *d __unused)
2606558b565SEtienne Carriere {
2616558b565SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
2626558b565SEtienne Carriere }
2636558b565SEtienne Carriere #endif /* CFG_DRIVERS_REGULATOR && CFG_DT */
2646558b565SEtienne Carriere
2651a3d3273SEtienne Carriere /*
2661a3d3273SEtienne Carriere * regulator_name() - Return regulator name or NULL
2671a3d3273SEtienne Carriere * @regulator: Regulator reference
2681a3d3273SEtienne Carriere */
regulator_name(struct regulator * regulator)2691a3d3273SEtienne Carriere static inline const char *regulator_name(struct regulator *regulator)
2701a3d3273SEtienne Carriere {
2711a3d3273SEtienne Carriere return regulator->name;
2721a3d3273SEtienne Carriere }
2731a3d3273SEtienne Carriere
2741a3d3273SEtienne Carriere /*
275e3830fc7SEtienne Carriere * regulator_is_always_on() - Return the state of REGULATOR_ALWAYS_ON flag
276e3830fc7SEtienne Carriere * @regulator: Regulator reference
277e3830fc7SEtienne Carriere */
regulator_is_always_on(struct regulator * regulator)278e3830fc7SEtienne Carriere static inline bool regulator_is_always_on(struct regulator *regulator)
279e3830fc7SEtienne Carriere {
280e3830fc7SEtienne Carriere return regulator->flags & REGULATOR_ALWAYS_ON;
281e3830fc7SEtienne Carriere }
282e3830fc7SEtienne Carriere
283e3830fc7SEtienne Carriere /*
2841a3d3273SEtienne Carriere * regulator_set_min_voltage() - Set regulator to its min level
2851a3d3273SEtienne Carriere * @regulator: Regulator reference
2861a3d3273SEtienne Carriere */
regulator_set_min_voltage(struct regulator * regulator)2871a3d3273SEtienne Carriere static inline TEE_Result regulator_set_min_voltage(struct regulator *regulator)
2881a3d3273SEtienne Carriere {
2891a3d3273SEtienne Carriere return regulator_set_voltage(regulator, regulator->min_uv);
2901a3d3273SEtienne Carriere }
2911a3d3273SEtienne Carriere
2921a3d3273SEtienne Carriere /*
293b4d1c08aSPatrick Delaunay * regulator_get_voltage() - Get regulator effective voltage level in microvolt
2941a3d3273SEtienne Carriere * @regulator: Regulator reference
2951a3d3273SEtienne Carriere */
296b4d1c08aSPatrick Delaunay int regulator_get_voltage(struct regulator *regulator);
2971a3d3273SEtienne Carriere
2981a3d3273SEtienne Carriere /*
2991a3d3273SEtienne Carriere * regulator_get_range() - Get regulator min and/or max support levels
3001a3d3273SEtienne Carriere * @regulator: Regulator reference
3011a3d3273SEtienne Carriere * @min_mv: Output reference to min level in microvolt (uV) or NULL
3021a3d3273SEtienne Carriere * @max_mv: Output reference to max level in microvolt (uV) or NULL
3031a3d3273SEtienne Carriere */
regulator_get_range(struct regulator * regulator,int * min_uv,int * max_uv)3041a3d3273SEtienne Carriere static inline void regulator_get_range(struct regulator *regulator, int *min_uv,
3051a3d3273SEtienne Carriere int *max_uv)
3061a3d3273SEtienne Carriere {
3071a3d3273SEtienne Carriere assert(regulator);
3081a3d3273SEtienne Carriere if (min_uv)
3091a3d3273SEtienne Carriere *min_uv = regulator->min_uv;
3101a3d3273SEtienne Carriere if (max_uv)
3111a3d3273SEtienne Carriere *max_uv = regulator->max_uv;
3121a3d3273SEtienne Carriere }
31343c155baSEtienne Carriere
31443c155baSEtienne Carriere /*
31543c155baSEtienne Carriere * regulator_supported_voltages() - Get regulator supported levels in microvolt
31643c155baSEtienne Carriere * @regulator: Regulator reference
317ace929f0SEtienne Carriere * @desc: Output reference to supported voltage levels description
318ace929f0SEtienne Carriere * @levels: Output reference to voltage level array, in microvolts
319ace929f0SEtienne Carriere *
320ace929f0SEtienne Carriere * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels
321ace929f0SEtienne Carriere * is defined by @desc->num_levels, each cell being a level in microvolts (uV).
322ace929f0SEtienne Carriere * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells:
323ace929f0SEtienne Carriere * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2]
324ace929f0SEtienne Carriere * is the incremental level step, all in microvolts (uV).
32543c155baSEtienne Carriere */
32643c155baSEtienne Carriere TEE_Result regulator_supported_voltages(struct regulator *regulator,
327ace929f0SEtienne Carriere struct regulator_voltages_desc **desc,
328ace929f0SEtienne Carriere const int **levels);
329c4292779SEtienne Carriere
3303c1b8123SPascal Paillet /* Print current regulator tree summary to console with info trace level */
331c4292779SEtienne Carriere #ifdef CFG_DRIVERS_REGULATOR
332c4292779SEtienne Carriere void regulator_print_tree(void);
333c4292779SEtienne Carriere #else
regulator_print_tree(void)334c4292779SEtienne Carriere static inline void regulator_print_tree(void)
335c4292779SEtienne Carriere {
336c4292779SEtienne Carriere }
337c4292779SEtienne Carriere #endif /* CFG_DRIVERS_REGULATOR */
338d50fee03SEtienne Carriere #endif /* __DRIVERS_REGULATOR_H */
339