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, &current_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