1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_npm1100
7 
8 #include <errno.h>
9 
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/regulator.h>
12 #include <zephyr/dt-bindings/regulator/npm1100.h>
13 #include <zephyr/toolchain.h>
14 
15 struct regulator_npm1100_pconfig {
16 	struct gpio_dt_spec iset;
17 };
18 
19 struct regulator_npm1100_config {
20 	struct regulator_common_config common;
21 	struct gpio_dt_spec mode;
22 };
23 
24 struct regulator_npm1100_data {
25 	struct regulator_common_data data;
26 };
27 
regulator_npm1100_set_mode(const struct device * dev,regulator_mode_t mode)28 static int regulator_npm1100_set_mode(const struct device *dev,
29 				      regulator_mode_t mode)
30 {
31 	const struct regulator_npm1100_config *config = dev->config;
32 
33 	if ((config->mode.port == NULL) || (mode > NPM1100_MODE_PWM)) {
34 		return -ENOTSUP;
35 	}
36 
37 	return gpio_pin_set_dt(&config->mode,
38 			       mode == NPM1100_MODE_AUTO ? 0 : 1);
39 }
40 
regulator_npm1100_get_mode(const struct device * dev,regulator_mode_t * mode)41 static int regulator_npm1100_get_mode(const struct device *dev,
42 				      regulator_mode_t *mode)
43 {
44 	const struct regulator_npm1100_config *config = dev->config;
45 	int ret;
46 
47 	if (config->mode.port == NULL) {
48 		return -ENOTSUP;
49 	}
50 
51 	ret = gpio_pin_get_dt(&config->mode);
52 	if (ret < 0) {
53 		return ret;
54 	}
55 
56 	*mode = (ret == 0) ? NPM1100_MODE_AUTO : NPM1100_MODE_PWM;
57 
58 	return 0;
59 }
60 
regulator_npm1100_init(const struct device * dev)61 static __unused int regulator_npm1100_init(const struct device *dev)
62 {
63 	const struct regulator_npm1100_config *config = dev->config;
64 	int ret;
65 
66 	if (config->mode.port != NULL) {
67 		if (!gpio_is_ready_dt(&config->mode)) {
68 			return -ENODEV;
69 		}
70 
71 		ret = gpio_pin_configure_dt(&config->mode,
72 					    GPIO_INPUT | GPIO_OUTPUT_INACTIVE);
73 		if (ret < 0) {
74 			return ret;
75 		}
76 	}
77 
78 	regulator_common_data_init(dev);
79 
80 	return regulator_common_init(dev, true);
81 }
82 
regulator_npm1100_common_init(const struct device * dev)83 static int regulator_npm1100_common_init(const struct device *dev)
84 {
85 	const struct regulator_npm1100_pconfig *config = dev->config;
86 
87 	if (config->iset.port != NULL) {
88 		int ret;
89 
90 		if (!gpio_is_ready_dt(&config->iset)) {
91 			return -ENODEV;
92 		}
93 
94 		ret = gpio_pin_configure_dt(&config->iset,
95 					    GPIO_OUTPUT_INACTIVE);
96 		if (ret < 0) {
97 			return ret;
98 		}
99 	}
100 
101 	return 0;
102 }
103 
104 static const __unused struct regulator_driver_api api = {
105 	.set_mode = regulator_npm1100_set_mode,
106 	.get_mode = regulator_npm1100_get_mode,
107 };
108 
109 #define REGULATOR_NPM1100_DEFINE_BUCK(node_id, id)                             \
110 	static struct regulator_npm1100_data data_##id;                        \
111                                                                                \
112 	static const struct regulator_npm1100_config config_##id = {           \
113 		.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id),            \
114 		.mode = GPIO_DT_SPEC_GET_OR(node_id, nordic_mode_gpios, {}),   \
115 	};                                                                     \
116                                                                                \
117 	DEVICE_DT_DEFINE(node_id, regulator_npm1100_init, NULL, &data_##id,    \
118 			 &config_##id, POST_KERNEL,                            \
119 			 CONFIG_REGULATOR_NPM1100_INIT_PRIORITY, &api);
120 
121 #define REGULATOR_NPM1100_DEFINE_BUCK_COND(inst)                               \
122 	COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, buck)),                 \
123 		    (REGULATOR_NPM1100_DEFINE_BUCK(DT_INST_CHILD(inst, buck),  \
124 						   buck##inst)),               \
125 		    ())
126 
127 #define REGULATOR_NPM1100_DEFINE_ALL(inst)                                     \
128 	static const struct regulator_npm1100_pconfig config_##inst = {        \
129 		.iset = GPIO_DT_SPEC_INST_GET_OR(inst, nordic_iset_gpios, {}), \
130 	};                                                                     \
131                                                                                \
132 	DEVICE_DT_INST_DEFINE(inst, regulator_npm1100_common_init, NULL, NULL, \
133 			      &config_##inst, POST_KERNEL,                     \
134 			      CONFIG_REGULATOR_NPM1100_INIT_PRIORITY, NULL);   \
135                                                                                \
136 	REGULATOR_NPM1100_DEFINE_BUCK_COND(inst)
137 
138 DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1100_DEFINE_ALL)
139