1 /*
2 * Copyright (c) 2023 Martin Kiepfer <mrmarteng@teleschirm.org>
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <errno.h>
7 #include <stdbool.h>
8
9 #include <zephyr/drivers/mfd/axp192.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/logging/log.h>
13
14 LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL);
15
16 struct mfd_axp192_config {
17 struct i2c_dt_spec i2c;
18 #ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED
19 bool vbusen_disable;
20 #endif
21 uint8_t reg_chip_id;
22 uint8_t vbus_config_reg;
23 uint8_t chip_id;
24 uint8_t val_vbusen_disable;
25 };
26
27 #ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED
28
29 /* Chip ID value */
30 #define AXP192_CHIP_ID 0x03U
31
32 /* Registers definitions */
33 #define AXP192_REG_CHIP_ID 0x03U
34
35 /* AXP192 GPIO register addresses */
36 #define AXP192_EXTEN_DCDC2_CONTROL_REG 0x10U
37 #define AXP192_VBUS_CFG_REG 0x30U
38 #define AXP192_GPIO0_FUNC_REG 0x90U
39 #define AXP192_GPIO1_FUNC_REG 0x92U
40 #define AXP192_GPIO2_FUNC_REG 0x93U
41 #define AXP192_GPIO34_FUNC_REG 0x95U
42 #define AXP192_GPIO012_PINVAL_REG 0x94U
43 #define AXP192_GPIO34_PINVAL_REG 0x96U
44 #define AXP192_GPIO012_PULLDOWN_REG 0x97U
45
46 /* VBUS control reg values */
47 #define AXP192_VBUS_CFG_VAL_VBUSEN_DISABLE 0x80U
48
49 /* GPIO function control parameters */
50 #define AXP192_GPIO012_FUNC_VAL_OUTPUT_OD 0x00U
51 #define AXP192_GPIO012_FUNC_VAL_INPUT 0x01U
52 #define AXP192_GPIO012_FUNC_VAL_LDO 0x02U /* only applicable for GPIO0 */
53 #define AXP192_GPIO012_FUNC_VAL_ADC 0x04U
54 #define AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW 0x05U
55 #define AXP192_GPIO012_FUNC_VAL_FLOAT 0x06U
56 #define AXP192_GPIO012_FUNC_MASK \
57 (AXP192_GPIO012_FUNC_VAL_OUTPUT_OD | AXP192_GPIO012_FUNC_VAL_INPUT | \
58 AXP192_GPIO012_FUNC_VAL_LDO | AXP192_GPIO012_FUNC_VAL_ADC | \
59 AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW | AXP192_GPIO012_FUNC_VAL_FLOAT)
60
61 #define AXP192_GPIO34_FUNC_ENA 0x80U
62 #define AXP192_GPIO3_FUNC_VAL_CHARGE_CTL 0x00U
63 #define AXP192_GPIO3_FUNC_VAL_OUTPUT_OD 0x01U
64 #define AXP192_GPIO3_FUNC_VAL_INPUT 0x02U
65 #define AXP192_GPIO3_FUNC_MASK \
66 (AXP192_GPIO34_FUNC_ENA | AXP192_GPIO3_FUNC_VAL_CHARGE_CTL | \
67 AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO3_FUNC_VAL_INPUT)
68
69 #define AXP192_GPIO4_FUNC_VAL_CHARGE_CTL 0x00U
70 #define AXP192_GPIO4_FUNC_VAL_OUTPUT_OD 0x04U
71 #define AXP192_GPIO4_FUNC_VAL_INPUT 0x08U
72 #define AXP192_GPIO4_FUNC_VAL_ADC 0x0CU
73 #define AXP192_GPIO4_FUNC_MASK \
74 (AXP192_GPIO34_FUNC_ENA | AXP192_GPIO4_FUNC_VAL_CHARGE_CTL | \
75 AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO4_FUNC_VAL_INPUT)
76
77 #define AXP192_EXTEN_ENA 0x04U
78 #define AXP192_EXTEN_MASK 0x04U
79
80 /* Pull-Down enable parameters */
81 #define AXP192_GPIO0_PULLDOWN_ENABLE 0x01U
82 #define AXP192_GPIO1_PULLDOWN_ENABLE 0x02U
83 #define AXP192_GPIO2_PULLDOWN_ENABLE 0x04U
84
85 /* GPIO Value parameters */
86 #define AXP192_GPIO0_INPUT_VAL 0x10U
87 #define AXP192_GPIO1_INPUT_VAL 0x20U
88 #define AXP192_GPIO2_INPUT_VAL 0x40U
89 #define AXP192_GPIO012_INTPUT_SHIFT 4U
90 #define AXP192_GPIO012_INTPUT_MASK \
91 (AXP192_GPIO0_INPUT_VAL | AXP192_GPIO1_INPUT_VAL | AXP192_GPIO2_INPUT_VAL)
92 #define AXP192_GPIO3_INPUT_VAL 0x10U
93 #define AXP192_GPIO4_INPUT_VAL 0x20U
94 #define AXP192_GPIO34_INTPUT_SHIFT 4U
95 #define AXP192_GPIO34_INTPUT_MASK (AXP192_GPIO3_INPUT_VAL | AXP192_GPIO4_INPUT_VAL)
96
97 #define AXP192_GPIO0_OUTPUT_VAL 0x01U
98 #define AXP192_GPIO1_OUTPUT_VAL 0x02U
99 #define AXP192_GPIO2_OUTPUT_VAL 0x04U
100 #define AXP192_GPIO012_OUTPUT_MASK \
101 (AXP192_GPIO0_OUTPUT_VAL | AXP192_GPIO1_OUTPUT_VAL | AXP192_GPIO2_OUTPUT_VAL)
102
103 #define AXP192_GPIO3_OUTPUT_VAL 0x01U
104 #define AXP192_GPIO4_OUTPUT_VAL 0x02U
105 #define AXP192_GPIO34_OUTPUT_MASK (AXP192_GPIO3_OUTPUT_VAL | AXP192_GPIO4_OUTPUT_VAL)
106
107 #define AXP192_GPIO5_OUTPUT_MASK 0x04U
108 #define AXP192_GPIO5_OUTPUT_VAL 0x04U
109 #define AXP192_GPIO5_OUTPUT_SHIFT 3U
110
111 struct mfd_axp192_data {
112 const struct device *gpio_mask_used[AXP192_GPIO_MAX_NUM];
113 uint8_t gpio_mask_output;
114 };
115
116 struct mfd_axp192_func_reg_desc {
117 uint8_t reg;
118 uint8_t mask;
119 };
120
121 const struct mfd_axp192_func_reg_desc gpio_reg_desc[AXP192_GPIO_MAX_NUM] = {
122 {
123 /* GPIO0 */
124 .reg = AXP192_GPIO0_FUNC_REG,
125 .mask = AXP192_GPIO012_FUNC_MASK,
126 },
127 {
128 /* GPIO1 */
129 .reg = AXP192_GPIO1_FUNC_REG,
130 .mask = AXP192_GPIO012_FUNC_MASK,
131 },
132 {
133 /* GPIO2 */
134 .reg = AXP192_GPIO2_FUNC_REG,
135 .mask = AXP192_GPIO012_FUNC_MASK,
136 },
137 {
138 /* GPIO3 */
139 .reg = AXP192_GPIO34_FUNC_REG,
140 .mask = AXP192_GPIO3_FUNC_MASK,
141 },
142 {
143 /* GPIO4 */
144 .reg = AXP192_GPIO34_FUNC_REG,
145 .mask = AXP192_GPIO4_FUNC_MASK,
146 },
147 };
148 #endif /* CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED */
149
150 #ifdef CONFIG_DT_HAS_X_POWERS_AXP2101_ENABLED
151
152 /* Chip ID value */
153 #define AXP2101_CHIP_ID 0x4AU
154
155 /* Registers definitions */
156 #define AXP2101_REG_CHIP_ID 0x03U
157
158 /* AXP210 GPIO register addresses */
159 #define AXP2101_VBUS_CFG_REG 0x00U
160
161 /* VBUS control reg values */
162 #define AXP2101_VBUS_CFG_VAL_VBUSEN_DISABLE 0x00U
163 #endif /* CONFIG_DT_HAS_X_POWERS_AXP2101_ENABLED */
164
mfd_axp192_init(const struct device * dev)165 static int mfd_axp192_init(const struct device *dev)
166 {
167 const struct mfd_axp192_config *config = dev->config;
168 uint8_t chip_id;
169 int ret;
170
171 LOG_DBG("Initializing instance");
172
173 if (!i2c_is_ready_dt(&config->i2c)) {
174 LOG_ERR("I2C bus not ready");
175 return -ENODEV;
176 }
177
178 /* Check if axp192 chip is available */
179 ret = i2c_reg_read_byte_dt(&config->i2c, config->reg_chip_id, &chip_id);
180 if (ret < 0) {
181 return ret;
182 }
183 if (chip_id != config->chip_id) {
184 LOG_ERR("Invalid Chip detected (%d)", chip_id);
185 return -EINVAL;
186 }
187
188 #ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED
189 /* Disable N_VBUSEN */
190 ret = i2c_reg_update_byte_dt(
191 &config->i2c, config->vbus_config_reg, config->val_vbusen_disable,
192 config->vbusen_disable ? config->val_vbusen_disable : 0);
193 if (ret < 0) {
194 return ret;
195 }
196 #endif
197
198 return 0;
199 }
200
201 #ifdef CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED
mfd_axp192_gpio_func_get(const struct device * dev,uint8_t gpio,enum axp192_gpio_func * func)202 int mfd_axp192_gpio_func_get(const struct device *dev, uint8_t gpio, enum axp192_gpio_func *func)
203 {
204 const struct mfd_axp192_config *config = dev->config;
205 int ret;
206 uint8_t reg_fnc;
207
208 if (gpio >= AXP192_GPIO_MAX_NUM) {
209 LOG_ERR("Invalid gpio (%d)", gpio);
210 return -EINVAL;
211 }
212
213 if (gpio < ARRAY_SIZE(gpio_reg_desc)) {
214 ret = i2c_reg_read_byte_dt(&(config->i2c), gpio_reg_desc[gpio].reg, ®_fnc);
215 if (ret != 0) {
216 return ret;
217 }
218 }
219
220 switch (gpio) {
221 case 0U:
222 __fallthrough;
223 case 1U:
224 __fallthrough;
225 case 2U:
226 /* GPIO 0-2*/
227 switch (reg_fnc) {
228 case AXP192_GPIO012_FUNC_VAL_INPUT:
229 *func = AXP192_GPIO_FUNC_INPUT;
230 break;
231 case AXP192_GPIO012_FUNC_VAL_OUTPUT_OD:
232 *func = AXP192_GPIO_FUNC_OUTPUT_OD;
233 break;
234 case AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW:
235 *func = AXP192_GPIO_FUNC_OUTPUT_LOW;
236 break;
237 case AXP192_GPIO012_FUNC_VAL_LDO:
238 if (gpio == 0) {
239 /* LDO is only applicable on GPIO0 */
240 *func = AXP192_GPIO_FUNC_LDO;
241 } else {
242 ret = -ENOTSUP;
243 }
244 break;
245 case AXP192_GPIO012_FUNC_VAL_ADC:
246 *func = AXP192_GPIO_FUNC_ADC;
247 break;
248 case AXP192_GPIO012_FUNC_VAL_FLOAT:
249 *func = AXP192_GPIO_FUNC_FLOAT;
250 break;
251 default:
252 ret = -ENOTSUP;
253 break;
254 }
255 break;
256
257 case 3U:
258 /* GPIO3 */
259 switch (reg_fnc) {
260 case (AXP192_GPIO3_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA):
261 *func = AXP192_GPIO_FUNC_INPUT;
262 break;
263 case (AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA):
264 *func = AXP192_GPIO_FUNC_OUTPUT_OD;
265 break;
266 case AXP192_GPIO3_FUNC_VAL_CHARGE_CTL:
267 *func = AXP192_GPIO_FUNC_CHARGE_CTL;
268 break;
269 default:
270 ret = -ENOTSUP;
271 break;
272 }
273 break;
274
275 case 4U:
276 /* GPIO4 */
277 switch (reg_fnc) {
278 case (AXP192_GPIO4_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA):
279 *func = AXP192_GPIO_FUNC_INPUT;
280 break;
281 case (AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA):
282 *func = AXP192_GPIO_FUNC_OUTPUT_OD;
283 break;
284 case (AXP192_GPIO4_FUNC_VAL_ADC | AXP192_GPIO34_FUNC_ENA):
285 *func = AXP192_GPIO_FUNC_ADC;
286 break;
287 case AXP192_GPIO4_FUNC_VAL_CHARGE_CTL:
288 *func = AXP192_GPIO_FUNC_CHARGE_CTL;
289 break;
290 default:
291 ret = -ENOTSUP;
292 break;
293 }
294 break;
295
296 case 5U:
297 /* EXTEN is an output only pin */
298 *func = AXP192_GPIO_FUNC_OUTPUT_LOW;
299 break;
300
301 default:
302 ret = -EINVAL;
303 }
304
305 return ret;
306 }
307
mfd_axp192_gpio_func_ctrl(const struct device * dev,const struct device * client_dev,uint8_t gpio,enum axp192_gpio_func func)308 int mfd_axp192_gpio_func_ctrl(const struct device *dev, const struct device *client_dev,
309 uint8_t gpio, enum axp192_gpio_func func)
310 {
311 const struct mfd_axp192_config *config = dev->config;
312 struct mfd_axp192_data *data = dev->data;
313 bool is_output = false;
314 int ret = 0;
315 uint8_t reg_cfg = 0;
316
317 if (!AXP192_GPIO_FUNC_VALID(func)) {
318 LOG_ERR("Invalid function");
319 return -EINVAL;
320 }
321
322 if (gpio >= AXP192_GPIO_MAX_NUM) {
323 LOG_ERR("Invalid gpio (%d)", gpio);
324 return -EINVAL;
325 }
326
327 if ((data->gpio_mask_used[gpio] != 0) && (data->gpio_mask_used[gpio] != client_dev)) {
328 LOG_INF("Warning: Pin already configured. Please check dt configuration");
329 }
330
331 switch (gpio) {
332 case 0U:
333 __fallthrough;
334 case 1U:
335 __fallthrough;
336 case 2U:
337 /* GPIO 0-2*/
338 switch (func) {
339 case AXP192_GPIO_FUNC_INPUT:
340 reg_cfg = AXP192_GPIO012_FUNC_VAL_INPUT;
341 break;
342 case AXP192_GPIO_FUNC_OUTPUT_OD:
343 reg_cfg = AXP192_GPIO012_FUNC_VAL_OUTPUT_OD;
344 is_output = true;
345 break;
346 case AXP192_GPIO_FUNC_OUTPUT_LOW:
347 reg_cfg = AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW;
348 is_output = true;
349 break;
350 case AXP192_GPIO_FUNC_LDO:
351 if (gpio == 0) {
352 /* LDO is only applicable on GPIO0 */
353 reg_cfg = AXP192_GPIO012_FUNC_VAL_LDO;
354 } else {
355 ret = -ENOTSUP;
356 }
357 break;
358 case AXP192_GPIO_FUNC_ADC:
359 reg_cfg = AXP192_GPIO012_FUNC_VAL_ADC;
360 break;
361 case AXP192_GPIO_FUNC_FLOAT:
362 reg_cfg = AXP192_GPIO012_FUNC_VAL_FLOAT;
363 break;
364 default:
365 ret = -ENOTSUP;
366 break;
367 }
368 break;
369
370 case 3U:
371 /* GPIO3 */
372 switch (func) {
373 case AXP192_GPIO_FUNC_INPUT:
374 reg_cfg = AXP192_GPIO3_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA;
375 break;
376 case AXP192_GPIO_FUNC_OUTPUT_OD:
377 reg_cfg = AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA;
378 is_output = true;
379 break;
380 case AXP192_GPIO_FUNC_CHARGE_CTL:
381 reg_cfg = AXP192_GPIO3_FUNC_VAL_CHARGE_CTL;
382 break;
383 default:
384 ret = -ENOTSUP;
385 break;
386 }
387 break;
388
389 case 4U:
390 /* GPIO4 */
391 switch (func) {
392 case AXP192_GPIO_FUNC_INPUT:
393 reg_cfg = AXP192_GPIO4_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA;
394 break;
395 case AXP192_GPIO_FUNC_OUTPUT_OD:
396 reg_cfg = AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA;
397 is_output = true;
398 break;
399 case AXP192_GPIO_FUNC_ADC:
400 reg_cfg = AXP192_GPIO4_FUNC_VAL_ADC | AXP192_GPIO34_FUNC_ENA;
401 break;
402 case AXP192_GPIO_FUNC_CHARGE_CTL:
403 reg_cfg = AXP192_GPIO4_FUNC_VAL_CHARGE_CTL;
404 break;
405 default:
406 ret = -ENOTSUP;
407 break;
408 }
409 break;
410
411 case 5U:
412 /* EXTEN is an output only pin */
413 break;
414
415 default:
416 ret = -EINVAL;
417 }
418
419 if (ret != 0) {
420 LOG_ERR("Invalid function (0x%x) for gpio %d", func, gpio);
421 return ret;
422 }
423
424 if (gpio < ARRAY_SIZE(gpio_reg_desc)) {
425 ret = i2c_reg_update_byte_dt(&(config->i2c), gpio_reg_desc[gpio].reg,
426 gpio_reg_desc[gpio].mask, reg_cfg);
427 if (ret != 0) {
428 return ret;
429 }
430 }
431
432 /* Save gpio configuration state */
433 data->gpio_mask_used[gpio] = client_dev;
434 if (is_output) {
435 data->gpio_mask_output |= (1u << gpio);
436 } else {
437 data->gpio_mask_output &= ~(1u << gpio);
438 }
439 LOG_DBG("GPIO %d configured successfully (func=0x%x)", gpio, reg_cfg);
440
441 return 0;
442 }
443
mfd_axp192_gpio_pd_get(const struct device * dev,uint8_t gpio,bool * enabled)444 int mfd_axp192_gpio_pd_get(const struct device *dev, uint8_t gpio, bool *enabled)
445 {
446 const struct mfd_axp192_config *config = dev->config;
447 uint8_t gpio_val;
448 uint8_t pd_reg_mask = 0;
449 int ret = 0;
450
451 switch (gpio) {
452 case 0U:
453 pd_reg_mask = AXP192_GPIO0_PULLDOWN_ENABLE;
454 break;
455 case 1U:
456 pd_reg_mask = AXP192_GPIO1_PULLDOWN_ENABLE;
457 break;
458 case 2U:
459 pd_reg_mask = AXP192_GPIO2_PULLDOWN_ENABLE;
460 break;
461
462 case 3U:
463 __fallthrough;
464 case 4U:
465 __fallthrough;
466 case 5U:
467 LOG_DBG("Pull-Down not support on gpio %d", gpio);
468 return -ENOTSUP;
469
470 default:
471 LOG_ERR("Invalid gpio (%d)", gpio);
472 return -EINVAL;
473 }
474
475 ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO012_PULLDOWN_REG, &gpio_val);
476
477 if (ret == 0) {
478 *enabled = ((gpio_val & pd_reg_mask) != 0);
479 LOG_DBG("Pull-Down stats of gpio %d: %d", gpio, *enabled);
480 }
481
482 return 0;
483 }
484
mfd_axp192_gpio_pd_ctrl(const struct device * dev,uint8_t gpio,bool enable)485 int mfd_axp192_gpio_pd_ctrl(const struct device *dev, uint8_t gpio, bool enable)
486 {
487 uint8_t reg_pd_val = 0;
488 uint8_t reg_pd_mask = 0;
489 const struct mfd_axp192_config *config = dev->config;
490 int ret = 0;
491
492 /* Configure pull-down. Pull-down is only supported by GPIO3 and GPIO4 */
493 switch (gpio) {
494 case 0U:
495 reg_pd_mask = AXP192_GPIO0_PULLDOWN_ENABLE;
496 if (enable) {
497 reg_pd_val = AXP192_GPIO0_PULLDOWN_ENABLE;
498 }
499 break;
500
501 case 1U:
502 reg_pd_mask = AXP192_GPIO1_PULLDOWN_ENABLE;
503 if (enable) {
504 reg_pd_val = AXP192_GPIO1_PULLDOWN_ENABLE;
505 }
506 break;
507
508 case 2U:
509 reg_pd_mask = AXP192_GPIO2_PULLDOWN_ENABLE;
510 if (enable) {
511 reg_pd_val = AXP192_GPIO2_PULLDOWN_ENABLE;
512 }
513 break;
514
515 case 3U:
516 __fallthrough;
517 case 4U:
518 __fallthrough;
519 case 5U:
520 LOG_ERR("Pull-Down not support on gpio %d", gpio);
521 return -ENOTSUP;
522
523 default:
524 LOG_ERR("Invalid gpio (%d)", gpio);
525 return -EINVAL;
526 }
527
528 ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO012_PULLDOWN_REG, reg_pd_mask,
529 reg_pd_val);
530
531 return ret;
532 }
533
mfd_axp192_gpio_read_port(const struct device * dev,uint8_t * value)534 int mfd_axp192_gpio_read_port(const struct device *dev, uint8_t *value)
535 {
536 const struct mfd_axp192_config *config = dev->config;
537 const struct mfd_axp192_data *data = dev->data;
538 int ret;
539 uint8_t gpio012_val;
540 uint8_t gpio34_val;
541 uint8_t gpio5_val;
542 uint8_t gpio_input_val;
543 uint8_t gpio_output_val;
544
545 /* read gpio0-2 */
546 ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO012_PINVAL_REG, &gpio012_val);
547 if (ret != 0) {
548 return ret;
549 }
550
551 /* read gpio3-4 */
552 ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO34_PINVAL_REG, &gpio34_val);
553 if (ret != 0) {
554 return ret;
555 }
556
557 /* read gpio5 */
558 ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_EXTEN_DCDC2_CONTROL_REG, &gpio5_val);
559 if (ret != 0) {
560 return ret;
561 }
562
563 LOG_DBG("GPIO012 pinval-reg=0x%x", gpio012_val);
564 LOG_DBG("GPIO34 pinval-reg =0x%x", gpio34_val);
565 LOG_DBG("GPIO5 pinval-reg =0x%x", gpio5_val);
566 LOG_DBG("Output-Mask =0x%x", data->gpio_mask_output);
567
568 gpio_input_val =
569 ((gpio012_val & AXP192_GPIO012_INTPUT_MASK) >> AXP192_GPIO012_INTPUT_SHIFT);
570 gpio_input_val |=
571 (((gpio34_val & AXP192_GPIO34_INTPUT_MASK) >> AXP192_GPIO34_INTPUT_SHIFT) << 3u);
572
573 gpio_output_val = (gpio012_val & AXP192_GPIO012_OUTPUT_MASK);
574 gpio_output_val |= ((gpio34_val & AXP192_GPIO34_OUTPUT_MASK) << 3u);
575 gpio_output_val |=
576 (((gpio5_val & AXP192_GPIO5_OUTPUT_MASK) >> AXP192_GPIO5_OUTPUT_SHIFT) << 5u);
577
578 *value = gpio_input_val & ~(data->gpio_mask_output);
579 *value |= (gpio_output_val & data->gpio_mask_output);
580
581 return 0;
582 }
583
mfd_axp192_gpio_write_port(const struct device * dev,uint8_t value,uint8_t mask)584 int mfd_axp192_gpio_write_port(const struct device *dev, uint8_t value, uint8_t mask)
585 {
586 const struct mfd_axp192_config *config = dev->config;
587 int ret;
588 uint8_t gpio_reg_val;
589 uint8_t gpio_reg_mask;
590
591 /* Write gpio0-2. Mask out other port pins */
592 gpio_reg_val = (value & AXP192_GPIO012_OUTPUT_MASK);
593 gpio_reg_mask = (mask & AXP192_GPIO012_OUTPUT_MASK);
594 if (gpio_reg_mask != 0) {
595 ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO012_PINVAL_REG,
596 gpio_reg_mask, gpio_reg_val);
597 if (ret != 0) {
598 return ret;
599 }
600 LOG_DBG("GPIO012 pinval-reg=0x%x mask=0x%x", gpio_reg_val, gpio_reg_mask);
601 }
602
603 /* Write gpio3-4. Mask out other port pins */
604 gpio_reg_val = value >> 3U;
605 gpio_reg_mask = (mask >> 3U) & AXP192_GPIO34_OUTPUT_MASK;
606 if (gpio_reg_mask != 0) {
607 ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO34_PINVAL_REG,
608 gpio_reg_mask, gpio_reg_val);
609 if (ret != 0) {
610 return ret;
611 }
612 LOG_DBG("GPIO34 pinval-reg =0x%x mask=0x%x", gpio_reg_val, gpio_reg_mask);
613 }
614
615 /* Write gpio5. Mask out other port pins */
616 if ((mask & BIT(5)) != 0) {
617 gpio_reg_mask = AXP192_EXTEN_MASK;
618 gpio_reg_val = (value & BIT(5)) ? AXP192_EXTEN_ENA : 0U;
619 ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_EXTEN_DCDC2_CONTROL_REG,
620 gpio_reg_mask, gpio_reg_val);
621 if (ret != 0) {
622 return ret;
623 }
624 LOG_DBG("GPIO5 pinval-reg =0x%x mask=0x%x\n", gpio_reg_val, gpio_reg_mask);
625 }
626
627 return 0;
628 }
629 #endif
630
631 #define MFD_AXP192_CONST_CONFIG(model) \
632 .reg_chip_id = AXP##model##_REG_CHIP_ID, \
633 .vbus_config_reg = AXP##model##_VBUS_CFG_REG, \
634 .chip_id = AXP##model##_CHIP_ID, \
635 .val_vbusen_disable = AXP##model##_CHIP_ID,
636
637 #define MFD_AXP192_AXP2101_DEFINE(node, model) \
638 static const struct mfd_axp192_config config##node = { \
639 .i2c = I2C_DT_SPEC_GET(node), \
640 IF_ENABLED(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \
641 (.vbusen_disable = DT_PROP_OR(node, vbusen_disable, false),)) \
642 MFD_AXP192_CONST_CONFIG(model) \
643 }; \
644 \
645 IF_ENABLED(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \
646 (static struct mfd_axp192_data data##node;)) \
647 \
648 DEVICE_DT_DEFINE(node, mfd_axp192_init, NULL, \
649 COND_CODE_1(CONFIG_DT_HAS_X_POWERS_AXP192_ENABLED, \
650 (&data##node), (NULL)), \
651 &config##node, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
652
653 DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp192, MFD_AXP192_AXP2101_DEFINE, 192);
654 DT_FOREACH_STATUS_OKAY_VARGS(x_powers_axp2101, MFD_AXP192_AXP2101_DEFINE, 2101);
655