1 /*
2 * Copyright 2022 Nordic Semiconductor ASA
3 * Copyright 2023 Meta Platforms
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/regulator.h>
9
regulator_delay(uint32_t delay_us)10 static void regulator_delay(uint32_t delay_us)
11 {
12 if (delay_us > 0U) {
13 #ifdef CONFIG_MULTITHREADING
14 k_sleep(K_USEC(delay_us));
15 #else
16 k_busy_wait(delay_us);
17 #endif
18 }
19 }
20
regulator_common_data_init(const struct device * dev)21 void regulator_common_data_init(const struct device *dev)
22 {
23 struct regulator_common_data *data = dev->data;
24
25 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
26 (void)k_mutex_init(&data->lock);
27 #endif
28 data->refcnt = 0;
29 }
30
regulator_common_init(const struct device * dev,bool is_enabled)31 int regulator_common_init(const struct device *dev, bool is_enabled)
32 {
33 const struct regulator_driver_api *api = dev->api;
34 const struct regulator_common_config *config = dev->config;
35 struct regulator_common_data *data = dev->data;
36 int32_t current_uv;
37 int ret;
38
39 if (config->initial_mode != REGULATOR_INITIAL_MODE_UNKNOWN) {
40 ret = regulator_set_mode(dev, config->initial_mode);
41 if (ret < 0) {
42 return ret;
43 }
44 }
45
46 if (REGULATOR_ACTIVE_DISCHARGE_GET_BITS(config->flags) !=
47 REGULATOR_ACTIVE_DISCHARGE_DEFAULT) {
48 ret = regulator_set_active_discharge(dev,
49 (bool)REGULATOR_ACTIVE_DISCHARGE_GET_BITS(config->flags));
50 if (ret < 0) {
51 return ret;
52 }
53 }
54
55 if (config->init_uv > INT32_MIN) {
56 ret = regulator_set_voltage(dev, config->init_uv, config->init_uv);
57 if (ret < 0) {
58 return ret;
59 }
60 }
61
62 if (config->init_ua > INT32_MIN) {
63 ret = regulator_set_current_limit(dev, config->init_ua, config->init_ua);
64 if (ret < 0) {
65 return ret;
66 }
67 }
68
69 /* If we have valid range values, we try to match them before enabling */
70 if ((config->min_uv > INT32_MIN) || (config->max_uv < INT32_MAX)) {
71
72 ret = regulator_get_voltage(dev, ¤t_uv);
73 if (ret < 0) {
74 return ret;
75 }
76
77 /* Snap to closest interval value if out of range */
78 if (current_uv < config->min_uv) {
79 ret = regulator_set_voltage(dev, config->min_uv, config->min_uv);
80 if (ret < 0) {
81 return ret;
82 }
83 } else if (current_uv > config->max_uv) {
84 ret = regulator_set_voltage(dev, config->max_uv, config->max_uv);
85 if (ret < 0) {
86 return ret;
87 }
88 }
89 }
90
91 if (is_enabled) {
92 data->refcnt++;
93 } else if ((config->flags & REGULATOR_INIT_ENABLED) != 0U) {
94 ret = api->enable(dev);
95 if (ret < 0) {
96 return ret;
97 }
98
99 regulator_delay(config->startup_delay_us);
100 data->refcnt++;
101 }
102
103 return 0;
104 }
105
regulator_enable(const struct device * dev)106 int regulator_enable(const struct device *dev)
107 {
108 const struct regulator_driver_api *api = dev->api;
109 const struct regulator_common_config *config = dev->config;
110 struct regulator_common_data *data = dev->data;
111 int ret = 0;
112
113 /* enable not supported (always on) */
114 if (api->enable == NULL) {
115 return 0;
116 }
117
118 /* regulator must stay always on */
119 if ((config->flags & REGULATOR_ALWAYS_ON) != 0U) {
120 return 0;
121 }
122
123 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
124 (void)k_mutex_lock(&data->lock, K_FOREVER);
125 #endif
126
127 data->refcnt++;
128
129 if (data->refcnt == 1) {
130 ret = api->enable(dev);
131 if (ret < 0) {
132 data->refcnt--;
133 } else {
134 regulator_delay(config->off_on_delay_us);
135 }
136 }
137
138 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
139 k_mutex_unlock(&data->lock);
140 #endif
141
142 return ret;
143 }
144
regulator_is_enabled(const struct device * dev)145 bool regulator_is_enabled(const struct device *dev)
146 {
147 const struct regulator_common_config *config = dev->config;
148 struct regulator_common_data *data = dev->data;
149 bool enabled;
150
151 if ((config->flags & REGULATOR_ALWAYS_ON) != 0U) {
152 enabled = true;
153 } else {
154 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
155 (void)k_mutex_lock(&data->lock, K_FOREVER);
156 #endif
157 enabled = data->refcnt != 0;
158 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
159 k_mutex_unlock(&data->lock);
160 #endif
161 }
162
163 return enabled;
164 }
165
regulator_disable(const struct device * dev)166 int regulator_disable(const struct device *dev)
167 {
168 const struct regulator_driver_api *api = dev->api;
169 const struct regulator_common_config *config = dev->config;
170 struct regulator_common_data *data = dev->data;
171 int ret = 0;
172
173 /* disable not supported (always on) */
174 if (api->disable == NULL) {
175 return 0;
176 }
177
178 /* regulator must stay always on */
179 if ((config->flags & REGULATOR_ALWAYS_ON) != 0U) {
180 return 0;
181 }
182
183 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
184 (void)k_mutex_lock(&data->lock, K_FOREVER);
185 #endif
186
187 data->refcnt--;
188
189 if (data->refcnt == 0) {
190 ret = api->disable(dev);
191 if (ret < 0) {
192 data->refcnt++;
193 }
194 }
195
196 #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT
197 k_mutex_unlock(&data->lock);
198 #endif
199
200 return ret;
201 }
202
regulator_is_supported_voltage(const struct device * dev,int32_t min_uv,int32_t max_uv)203 bool regulator_is_supported_voltage(const struct device *dev, int32_t min_uv,
204 int32_t max_uv)
205 {
206 const struct regulator_common_config *config = dev->config;
207 unsigned int volt_cnt;
208
209 /* voltage may not be allowed, even if supported */
210 if ((min_uv > config->max_uv) || (max_uv < config->min_uv)) {
211 return false;
212 }
213
214 volt_cnt = regulator_count_voltages(dev);
215
216 for (unsigned int idx = 0U; idx < volt_cnt; idx++) {
217 int32_t volt_uv;
218
219 (void)regulator_list_voltage(dev, idx, &volt_uv);
220
221 if ((volt_uv >= min_uv) && (volt_uv <= max_uv)) {
222 return true;
223 }
224 }
225
226 return false;
227 }
228
regulator_set_voltage(const struct device * dev,int32_t min_uv,int32_t max_uv)229 int regulator_set_voltage(const struct device *dev, int32_t min_uv,
230 int32_t max_uv)
231 {
232 const struct regulator_common_config *config = dev->config;
233 const struct regulator_driver_api *api = dev->api;
234
235 if (api->set_voltage == NULL) {
236 return -ENOSYS;
237 }
238
239 /* voltage may not be allowed, even if supported */
240 if ((min_uv > config->max_uv) || (max_uv < config->min_uv)) {
241 return -EINVAL;
242 }
243
244 return api->set_voltage(dev, min_uv, max_uv);
245 }
246
regulator_set_current_limit(const struct device * dev,int32_t min_ua,int32_t max_ua)247 int regulator_set_current_limit(const struct device *dev, int32_t min_ua,
248 int32_t max_ua)
249 {
250 const struct regulator_common_config *config = dev->config;
251 const struct regulator_driver_api *api = dev->api;
252
253 if (api->set_current_limit == NULL) {
254 return -ENOSYS;
255 }
256
257 /* current limit may not be allowed, even if supported */
258 if ((min_ua > config->max_ua) || (max_ua < config->min_ua)) {
259 return -EINVAL;
260 }
261
262 return api->set_current_limit(dev, min_ua, max_ua);
263 }
264
regulator_set_mode(const struct device * dev,regulator_mode_t mode)265 int regulator_set_mode(const struct device *dev, regulator_mode_t mode)
266 {
267 const struct regulator_common_config *config = dev->config;
268 const struct regulator_driver_api *api = dev->api;
269
270 if (api->set_mode == NULL) {
271 return -ENOSYS;
272 }
273
274 /* no mode restrictions */
275 if (config->allowed_modes_cnt == 0U) {
276 return api->set_mode(dev, mode);
277 }
278
279 /* check if mode is allowed, apply if it is */
280 for (uint8_t i = 0U; i < config->allowed_modes_cnt; i++) {
281 if (mode == config->allowed_modes[i]) {
282 return api->set_mode(dev, mode);
283 }
284 }
285
286 return -ENOTSUP;
287 }
288