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