/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, STMicroelectronics */ #ifndef __DRIVERS_REGULATOR_H #define __DRIVERS_REGULATOR_H #include #include #include #include #include #include #include #include /* Regulator property flags: related to device tree binding properties */ /* Regulator should never be disabled. DT property: regulator-always-on */ #define REGULATOR_ALWAYS_ON BIT(0) /* Enables pull down mode. DT property: regulator-pull-down */ #define REGULATOR_PULL_DOWN BIT(1) /* * It's expected that this regulator was left on by the bootloader. * The core shouldn't prevent it from being turned off later. * DT property: regulator-boot-on */ #define REGULATOR_BOOT_ON BIT(2) #define REGULATOR_FLAGS_MASK (REGULATOR_ALWAYS_ON | REGULATOR_PULL_DOWN | \ REGULATOR_BOOT_ON) struct regulator_ops; /* * struct regu_dt_desc - Regulator description passed to regulator_dt_register() * @priv: Regulator driver private data * @name: Regulator string name for debug purpose * @supply_name: Regulator supply name for node property *-supply or NULL * @ops: Operation handlers for the regulator * @regulator: Pointer to preallocated regulator or NULL if none */ struct regu_dt_desc { void *priv; const char *name; const char *supply_name; const struct regulator_ops *ops; struct regulator *regulator; }; /* * Defines the format of struct voltages::entries * * If regulator_voltages::type is VOLTAGE_TYPE_FULL_LIST, then * regulator_voltages@entries stores regulator_voltages::num_levels cells, * listing supported voltage levels in uV from lowest to highest value. * * If regulator_voltages::type is VOLTAGE_TYPE_INCREMENT, then * regulator_voltages::entries stores 3 cells: min level, max level and * level increment step, all in uV. When so, regulator_voltages::num_levels * is meaningless. */ enum voltage_type { VOLTAGE_TYPE_INVALID = 0, VOLTAGE_TYPE_FULL_LIST, /* extensive list in uV */ VOLTAGE_TYPE_INCREMENT /* min, max, increment (in uV) */ }; /* * struct regulator_voltages_desc - Voltage levels description * @type: Type of level description * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST * */ struct regulator_voltages_desc { enum voltage_type type; size_t num_levels; }; /* * struct regulator - A regulator instance * @ops: Operation handlers for the regulator * @supply: Regulator supply reference or NULL if none * @priv: Regulator driver private data * @name: Regulator string name for debug purpose or NULL * @min_uv: Min possible voltage level in microvolt (uV) * @max_uv: Max possible voltage level in microvolt (uV) * @flags: REGULATOR_* property flags * @refcount: Regulator enable request reference counter * @mutex: Concurrent access protection considering PM context sequences * @voltages_fallback: Default supported voltage range description * @link: Link in initialized regulator list */ struct regulator { /* Fields initialized by caller of regulator_register() */ const struct regulator_ops *ops; struct regulator *supply; void *priv; char *name; int min_uv; int max_uv; /* Fields internal to regulator framework */ unsigned int flags; unsigned int refcount; struct mutex_pm_aware mutex; struct voltages_fallback { struct regulator_voltages_desc desc; int levels[3]; } voltages_fallback; size_t levels_count_fallback; SLIST_ENTRY(regulator) link; }; /* * struct regulator_ops - Regulator operation handlers * * @set_state: Enable or disable a regulator * @get_state: Get regulator effective state * @set_voltage: Set voltage level in microvolt (uV) * @get_voltage: Get current voltage in microvolt (uV) * @supported_voltages: Get supported levels description * @supplied_init: Optional, finalize initialization once supply is ready */ struct regulator_ops { TEE_Result (*set_state)(struct regulator *r, bool enabled); TEE_Result (*get_state)(struct regulator *r, bool *enabled); TEE_Result (*set_voltage)(struct regulator *r, int level_uv); TEE_Result (*get_voltage)(struct regulator *r, int *level_uv); TEE_Result (*supported_voltages)(struct regulator *r, struct regulator_voltages_desc **desc, const int **levels); TEE_Result (*supplied_init)(struct regulator *r, const void *fdt, int node); }; #ifdef CFG_DRIVERS_REGULATOR /* * regulator_enable() - Enable regulator * @regulator: Regulator reference */ TEE_Result regulator_enable(struct regulator *regulator); /* * regulator_disable() - Disable regulator * @regulator: Regulator reference */ TEE_Result regulator_disable(struct regulator *regulator); /* * regulator_is_enabled() - Return whether or not regulator is currently enabled * despite its refcount value. * @regulator: Regulator reference */ bool regulator_is_enabled(struct regulator *regulator); /* * regulator_set_voltage() - Set regulator to target level in microvolt * @regulator: Regulator reference * @level_uv: Level in microvolt */ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv); /* * regulator_register() - Register and initialize a regulator * @regulator: Regulator reference */ TEE_Result regulator_register(struct regulator *regulator); /* Print registered regulators and their state to the output console */ void regulator_print_state(const char *message); #else static inline TEE_Result regulator_enable(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result regulator_disable(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline bool regulator_is_enabled(struct regulator *regulator __unused) { return false; } static inline TEE_Result regulator_set_voltage(struct regulator *regul __unused, int level_mv __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result regulator_init(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void regulator_print_state(const char *message __unused) { } #endif /*CFG_DRIVERS_REGULATOR*/ #if defined(CFG_DRIVERS_REGULATOR) && defined(CFG_DT) /* * regulator_dt_get_supply() - Get a regulator supply from name and DT node * @fdt: FDT to work on * @node: DT node of the regulator consumer * @supply_name: Name of the supply in DT property xxx-supply * @regulator: Output regulator upon success * * Upon success, this function provides the pointer to regulator * defined by DT binding property @name-supply phandle reference. * * This function returns TEE_ERROR_DEFER_DRIVER_INIT if supply exists but is * not yet initialized. */ TEE_Result regulator_dt_get_supply(const void *fdt, int node, const char *supply_name, struct regulator **regulator); /* * regulator_dt_register() - Register a regulator to related to a DT node * @fdt: FDT to work on * @node: DT node of the regulator exposed by regulator driver * @provider_node: Node where xxx-supply property is found or -1 if no supply. * @desc: Description of the regulator to register * * This function registers and initializes a regulator instance once its supply * if found, if any. Regulators registered with this function can be found by * their consumer drivers using API function regulator_dt_get_supply() or like. * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_OUT_OF_MEMORY if failed on memory allocation * Return any other TEE_Result compliant code in case of error */ TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node, const struct regu_dt_desc *desc); #else static inline TEE_Result regulator_dt_get_supply(const void *fdt __unused, int node __unused, const char *supply __unused, struct regulator **r __unused) { return TEE_ERROR_NOT_SUPPORTED; } 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) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* CFG_DRIVERS_REGULATOR && CFG_DT */ /* * regulator_name() - Return regulator name or NULL * @regulator: Regulator reference */ static inline const char *regulator_name(struct regulator *regulator) { return regulator->name; } /* * regulator_is_always_on() - Return the state of REGULATOR_ALWAYS_ON flag * @regulator: Regulator reference */ static inline bool regulator_is_always_on(struct regulator *regulator) { return regulator->flags & REGULATOR_ALWAYS_ON; } /* * regulator_set_min_voltage() - Set regulator to its min level * @regulator: Regulator reference */ static inline TEE_Result regulator_set_min_voltage(struct regulator *regulator) { return regulator_set_voltage(regulator, regulator->min_uv); } /* * regulator_get_voltage() - Get regulator effective voltage level in microvolt * @regulator: Regulator reference */ int regulator_get_voltage(struct regulator *regulator); /* * regulator_get_range() - Get regulator min and/or max support levels * @regulator: Regulator reference * @min_mv: Output reference to min level in microvolt (uV) or NULL * @max_mv: Output reference to max level in microvolt (uV) or NULL */ static inline void regulator_get_range(struct regulator *regulator, int *min_uv, int *max_uv) { assert(regulator); if (min_uv) *min_uv = regulator->min_uv; if (max_uv) *max_uv = regulator->max_uv; } /* * regulator_supported_voltages() - Get regulator supported levels in microvolt * @regulator: Regulator reference * @desc: Output reference to supported voltage levels description * @levels: Output reference to voltage level array, in microvolts * * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels * is defined by @desc->num_levels, each cell being a level in microvolts (uV). * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells: * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2] * is the incremental level step, all in microvolts (uV). */ TEE_Result regulator_supported_voltages(struct regulator *regulator, struct regulator_voltages_desc **desc, const int **levels); /* Print current regulator tree summary to console with info trace level */ #ifdef CFG_DRIVERS_REGULATOR void regulator_print_tree(void); #else static inline void regulator_print_tree(void) { } #endif /* CFG_DRIVERS_REGULATOR */ #endif /* __DRIVERS_REGULATOR_H */