1 /*
2  * Copyright (c) 2021 NXP
3  * Copyright (c) 2023 Martin Kiepfer <mrmarteng@teleschirm.org>
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT x_powers_axp192_regulator
8 
9 #include <errno.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/drivers/regulator.h>
14 #include <zephyr/sys/linear_range.h>
15 #include <zephyr/sys/util.h>
16 #include <zephyr/dt-bindings/regulator/axp192.h>
17 #include <zephyr/logging/log.h>
18 #include <zephyr/logging/log_instance.h>
19 #include <zephyr/drivers/mfd/axp192.h>
20 
21 LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL);
22 
23 /* Output control registers */
24 #define AXP192_REG_EXTEN_DCDC2_CONTROL   0x10U
25 #define AXP192_REG_DCDC123_LDO23_CONTROL 0x12U
26 #define AXP192_REG_DCDC2_VOLTAGE         0x23U
27 #define AXP192_REG_DCDC2_SLOPE           0x25U
28 #define AXP192_REG_DCDC1_VOLTAGE         0x26U
29 #define AXP192_REG_DCDC3_VOLTAGE         0x27U
30 #define AXP192_REG_LDO23_VOLTAGE         0x28U
31 #define AXP192_REG_DCDC123_WORKMODE      0x80U
32 #define AXP192_REG_GPIO0_CONTROL         0x90U
33 #define AXP192_REG_LDOIO0_VOLTAGE        0x91U
34 
35 struct regulator_axp192_desc {
36 	const uint8_t enable_reg;
37 	const uint8_t enable_mask;
38 	const uint8_t enable_val;
39 	const uint8_t vsel_reg;
40 	const uint8_t vsel_mask;
41 	const uint8_t vsel_bitpos;
42 	const int32_t max_ua;
43 	const uint8_t workmode_reg;
44 	const uint8_t workmode_mask;
45 	const uint8_t workmode_pwm_val;
46 	const uint8_t num_ranges;
47 	const struct linear_range *ranges;
48 };
49 
50 struct regulator_axp192_data {
51 	struct regulator_common_data data;
52 };
53 
54 struct regulator_axp192_config {
55 	struct regulator_common_config common;
56 	const struct regulator_axp192_desc *desc;
57 	const struct device *mfd;
58 	const struct i2c_dt_spec i2c;
59 
60 	LOG_INSTANCE_PTR_DECLARE(log);
61 };
62 
63 static const struct linear_range dcdc1_ranges[] = {
64 	LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU),
65 };
66 
67 __maybe_unused static const struct regulator_axp192_desc dcdc1_desc = {
68 	.enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL,
69 	.enable_mask = 0x01U,
70 	.enable_val = 0x01U,
71 	.vsel_reg = AXP192_REG_DCDC1_VOLTAGE,
72 	.vsel_mask = 0x7FU,
73 	.vsel_bitpos = 0U,
74 	.max_ua = 1200000U,
75 	.workmode_reg = AXP192_REG_DCDC123_WORKMODE,
76 	.workmode_mask = 0x08U,
77 	.workmode_pwm_val = 0x08U,
78 	.ranges = dcdc1_ranges,
79 	.num_ranges = ARRAY_SIZE(dcdc1_ranges),
80 };
81 
82 static const struct linear_range dcdc2_ranges[] = {
83 	LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x3FU),
84 };
85 
86 __maybe_unused static const struct regulator_axp192_desc dcdc2_desc = {
87 	.enable_reg = AXP192_REG_EXTEN_DCDC2_CONTROL,
88 	.enable_mask = 0x01U,
89 	.enable_val = 0x01U,
90 	.vsel_reg = AXP192_REG_DCDC2_VOLTAGE,
91 	.vsel_mask = 0x3FU,
92 	.vsel_bitpos = 0U,
93 	.max_ua = 1600000U,
94 	.workmode_reg = AXP192_REG_DCDC123_WORKMODE,
95 	.workmode_mask = 0x04U,
96 	.workmode_pwm_val = 0x04U,
97 	.ranges = dcdc2_ranges,
98 	.num_ranges = ARRAY_SIZE(dcdc2_ranges),
99 };
100 
101 static const struct linear_range dcdc3_ranges[] = {
102 	LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU),
103 };
104 
105 __maybe_unused static const struct regulator_axp192_desc dcdc3_desc = {
106 	.enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL,
107 	.enable_mask = 0x02U,
108 	.enable_val = 0x02U,
109 	.vsel_reg = AXP192_REG_DCDC3_VOLTAGE,
110 	.vsel_mask = 0x7FU,
111 	.vsel_bitpos = 0U,
112 	.max_ua = 700000U,
113 	.workmode_reg = AXP192_REG_DCDC123_WORKMODE,
114 	.workmode_mask = 0x02U,
115 	.workmode_pwm_val = 0x02U,
116 	.ranges = dcdc3_ranges,
117 	.num_ranges = ARRAY_SIZE(dcdc3_ranges),
118 };
119 
120 static const struct linear_range ldoio0_ranges[] = {
121 	LINEAR_RANGE_INIT(1800000u, 100000u, 0x00u, 0x0Fu),
122 };
123 
124 __maybe_unused static const struct regulator_axp192_desc ldoio0_desc = {
125 	.enable_reg = AXP192_REG_GPIO0_CONTROL,
126 	.enable_mask = 0x07u,
127 	.enable_val = 0x03u,
128 	.vsel_reg = AXP192_REG_LDOIO0_VOLTAGE,
129 	.vsel_mask = 0xF0u,
130 	.vsel_bitpos = 4u,
131 	.max_ua = 50000u,
132 	.workmode_reg = 0u,
133 	.workmode_mask = 0u,
134 	.ranges = ldoio0_ranges,
135 	.num_ranges = ARRAY_SIZE(ldoio0_ranges),
136 };
137 
138 static const struct linear_range ldo2_ranges[] = {
139 	LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU),
140 };
141 
142 __maybe_unused static const struct regulator_axp192_desc ldo2_desc = {
143 	.enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL,
144 	.enable_mask = 0x04U,
145 	.enable_val = 0x04U,
146 	.vsel_reg = AXP192_REG_LDO23_VOLTAGE,
147 	.vsel_mask = 0xF0U,
148 	.vsel_bitpos = 4U,
149 	.max_ua = 200000U,
150 	.workmode_reg = 0U,
151 	.workmode_mask = 0U,
152 	.ranges = ldo2_ranges,
153 	.num_ranges = ARRAY_SIZE(ldo2_ranges),
154 };
155 
156 static const struct linear_range ldo3_ranges[] = {
157 	LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU),
158 };
159 
160 __maybe_unused static const struct regulator_axp192_desc ldo3_desc = {
161 	.enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL,
162 	.enable_mask = 0x08U,
163 	.enable_val = 0x08U,
164 	.vsel_reg = AXP192_REG_LDO23_VOLTAGE,
165 	.vsel_mask = 0x0FU,
166 	.vsel_bitpos = 0U,
167 	.max_ua = 200000U,
168 	.workmode_reg = 0U,
169 	.workmode_mask = 0U,
170 	.ranges = ldo3_ranges,
171 	.num_ranges = ARRAY_SIZE(ldo3_ranges),
172 };
173 
axp192_enable(const struct device * dev)174 static int axp192_enable(const struct device *dev)
175 {
176 	const struct regulator_axp192_config *config = dev->config;
177 	int ret;
178 
179 	LOG_INST_DBG(config->log, "Enabling regulator");
180 	LOG_INST_DBG(config->log, "[0x%02x]=0x%02x mask=0x%02x", config->desc->enable_reg,
181 		     config->desc->enable_val, config->desc->enable_mask);
182 
183 	/* special case for LDOIO0, which is multiplexed with GPIO0 */
184 	if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) {
185 		ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_LDO);
186 	} else {
187 		ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
188 					     config->desc->enable_mask, config->desc->enable_val);
189 	}
190 
191 	if (ret != 0) {
192 		LOG_INST_ERR(config->log, "Failed to enable regulator");
193 	}
194 
195 	return ret;
196 }
197 
axp192_disable(const struct device * dev)198 static int axp192_disable(const struct device *dev)
199 {
200 	const struct regulator_axp192_config *config = dev->config;
201 	int ret;
202 
203 	LOG_INST_DBG(config->log, "Disabling regulator");
204 	LOG_INST_DBG(config->log, "[0x%02x]=0 mask=0x%x", config->desc->enable_reg,
205 		     config->desc->enable_mask);
206 
207 	/* special case for LDOIO0, which is multiplexed with GPIO0 */
208 	if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) {
209 		ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_OUTPUT_LOW);
210 	} else {
211 		ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
212 					     config->desc->enable_mask, 0u);
213 	}
214 	if (ret != 0) {
215 		LOG_INST_ERR(config->log, "Failed to disable regulator");
216 	}
217 
218 	return ret;
219 }
220 
axp192_count_voltages(const struct device * dev)221 static unsigned int axp192_count_voltages(const struct device *dev)
222 {
223 	const struct regulator_axp192_config *config = dev->config;
224 
225 	return linear_range_group_values_count(config->desc->ranges, config->desc->num_ranges);
226 }
227 
axp192_list_voltage(const struct device * dev,unsigned int idx,int32_t * volt_uv)228 static int axp192_list_voltage(const struct device *dev, unsigned int idx, int32_t *volt_uv)
229 {
230 	const struct regulator_axp192_config *config = dev->config;
231 
232 	return linear_range_group_get_value(config->desc->ranges, config->desc->num_ranges, idx,
233 					    volt_uv);
234 }
235 
axp192_set_voltage(const struct device * dev,int32_t min_uv,int32_t max_uv)236 static int axp192_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv)
237 {
238 	const struct regulator_axp192_config *config = dev->config;
239 	uint16_t idx;
240 	int ret;
241 
242 	LOG_INST_DBG(config->log, "voltage = [min=%d, max=%d]", min_uv, max_uv);
243 
244 	/* set voltage */
245 	ret = linear_range_group_get_win_index(config->desc->ranges, config->desc->num_ranges,
246 					       min_uv, max_uv, &idx);
247 	if (ret != 0) {
248 		LOG_INST_ERR(config->log, "No voltage range window could be detected");
249 		return ret;
250 	}
251 
252 	idx <<= config->desc->vsel_bitpos;
253 
254 	LOG_INST_DBG(config->log, "[0x%x]=0x%x mask=0x%x", config->desc->vsel_reg, idx,
255 		     config->desc->vsel_mask);
256 	ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->vsel_reg, config->desc->vsel_mask,
257 				     (uint8_t)idx);
258 	if (ret != 0) {
259 		LOG_INST_ERR(config->log, "Failed to set regulator voltage");
260 	}
261 
262 	return ret;
263 }
264 
axp192_get_voltage(const struct device * dev,int32_t * volt_uv)265 static int axp192_get_voltage(const struct device *dev, int32_t *volt_uv)
266 {
267 	const struct regulator_axp192_config *config = dev->config;
268 	int ret;
269 	uint8_t raw_reg;
270 
271 	/* read voltage */
272 	ret = i2c_reg_read_byte_dt(&config->i2c, config->desc->vsel_reg, &raw_reg);
273 	if (ret != 0) {
274 		return ret;
275 	}
276 
277 	raw_reg = (raw_reg & config->desc->vsel_mask) >> config->desc->vsel_bitpos;
278 
279 	ret = linear_range_group_get_value(config->desc->ranges, config->desc->num_ranges, raw_reg,
280 					   volt_uv);
281 
282 	return ret;
283 }
284 
axp192_set_mode(const struct device * dev,regulator_mode_t mode)285 static int axp192_set_mode(const struct device *dev, regulator_mode_t mode)
286 {
287 	const struct regulator_axp192_config *config = dev->config;
288 	int ret;
289 
290 	/* setting workmode is only possible for DCDC1-3 */
291 	if ((mode == AXP192_DCDC_MODE_PWM) && (config->desc->workmode_reg != 0)) {
292 
293 		/* configure PWM mode */
294 		LOG_INST_DBG(config->log, "PWM mode enabled");
295 		ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->workmode_reg,
296 					     config->desc->workmode_mask,
297 					     config->desc->workmode_pwm_val);
298 		if (ret != 0) {
299 			return ret;
300 		}
301 	} else if (mode == AXP192_DCDC_MODE_AUTO) {
302 
303 		/* configure AUTO mode (default) */
304 		if (config->desc->workmode_reg != 0) {
305 			ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->workmode_reg,
306 						     config->desc->workmode_mask, 0u);
307 			if (ret != 0) {
308 				return ret;
309 			}
310 		} else {
311 
312 			/* AUTO is default mode for LDOs that cannot be configured */
313 			return 0;
314 		}
315 	} else {
316 		LOG_INST_ERR(config->log, "Setting DCDC workmode failed");
317 		return -ENOTSUP;
318 	}
319 
320 	return 0;
321 }
322 
axp192_get_current_limit(const struct device * dev,int32_t * curr_ua)323 static int axp192_get_current_limit(const struct device *dev, int32_t *curr_ua)
324 {
325 	const struct regulator_axp192_config *config = dev->config;
326 
327 	*curr_ua = config->desc->max_ua;
328 
329 	return 0;
330 }
331 
332 static DEVICE_API(regulator, api) = {
333 	.enable = axp192_enable,
334 	.disable = axp192_disable,
335 	.count_voltages = axp192_count_voltages,
336 	.list_voltage = axp192_list_voltage,
337 	.set_voltage = axp192_set_voltage,
338 	.get_voltage = axp192_get_voltage,
339 	.set_mode = axp192_set_mode,
340 	.get_current_limit = axp192_get_current_limit,
341 };
342 
regulator_axp192_init(const struct device * dev)343 static int regulator_axp192_init(const struct device *dev)
344 {
345 	const struct regulator_axp192_config *config = dev->config;
346 	uint8_t enabled_val;
347 	bool is_enabled;
348 	int ret = 0;
349 
350 	regulator_common_data_init(dev);
351 
352 	if (!device_is_ready(config->mfd)) {
353 		LOG_INST_ERR(config->log, "Parent instance not ready!");
354 		return -ENODEV;
355 	}
356 
357 	/* read regulator state */
358 	ret = i2c_reg_read_byte_dt(&config->i2c, config->desc->enable_reg, &enabled_val);
359 	if (ret != 0) {
360 		LOG_INST_ERR(config->log, "Reading enable status failed!");
361 		return ret;
362 	}
363 	is_enabled = ((enabled_val & config->desc->enable_mask) == config->desc->enable_val);
364 	LOG_INST_DBG(config->log, "is_enabled: %d", is_enabled);
365 
366 	return regulator_common_init(dev, is_enabled);
367 }
368 
369 #define REGULATOR_AXP192_DEFINE(node_id, id, name)                                                 \
370 	static struct regulator_axp192_data data_##id;                                             \
371 	LOG_INSTANCE_REGISTER(name, node_id, CONFIG_REGULATOR_LOG_LEVEL);                          \
372 	static const struct regulator_axp192_config config_##id = {                                \
373 		.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id),                                \
374 		.desc = &name##_desc,                                                              \
375 		.mfd = DEVICE_DT_GET(DT_GPARENT(node_id)),                                         \
376 		.i2c = I2C_DT_SPEC_GET(DT_GPARENT(node_id)),                                       \
377 		LOG_INSTANCE_PTR_INIT(log, name, node_id)};                                        \
378 	DEVICE_DT_DEFINE(node_id, regulator_axp192_init, NULL, &data_##id, &config_##id,           \
379 			 POST_KERNEL, CONFIG_REGULATOR_AXP192_INIT_PRIORITY, &api);
380 
381 #define REGULATOR_AXP192_DEFINE_COND(inst, child)                                                  \
382 	COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)),                                    \
383 		    (REGULATOR_AXP192_DEFINE(DT_INST_CHILD(inst, child), child##inst, child)), ())
384 
385 #define REGULATOR_AXP192_DEFINE_ALL(inst)                                                          \
386 	REGULATOR_AXP192_DEFINE_COND(inst, dcdc1)                                                  \
387 	REGULATOR_AXP192_DEFINE_COND(inst, dcdc2)                                                  \
388 	REGULATOR_AXP192_DEFINE_COND(inst, dcdc3)                                                  \
389 	REGULATOR_AXP192_DEFINE_COND(inst, ldoio0)                                                 \
390 	REGULATOR_AXP192_DEFINE_COND(inst, ldo2)                                                   \
391 	REGULATOR_AXP192_DEFINE_COND(inst, ldo3)
392 
393 DT_INST_FOREACH_STATUS_OKAY(REGULATOR_AXP192_DEFINE_ALL)
394