1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_npm1300_gpio
7 
8 #include <errno.h>
9 
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/gpio/gpio_utils.h>
12 #include <zephyr/drivers/mfd/npm1300.h>
13 #include <zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/util_macro.h>
16 
17 /* nPM1300 GPIO base address */
18 #define NPM_GPIO_BASE 0x06U
19 
20 /* nPM1300 GPIO registers offsets */
21 #define NPM_GPIO_OFFSET_MODE	  0x00U
22 #define NPM_GPIO_OFFSET_DRIVE	  0x05U
23 #define NPM_GPIO_OFFSET_PULLUP	  0x0AU
24 #define NPM_GPIO_OFFSET_PULLDOWN  0x0FU
25 #define NPM_GPIO_OFFSET_OPENDRAIN 0x14U
26 #define NPM_GPIO_OFFSET_DEBOUNCE  0x19U
27 #define NPM_GPIO_OFFSET_STATUS	  0x1EU
28 
29 /* nPM1300 Channel counts */
30 #define NPM1300_GPIO_PINS 5U
31 
32 #define NPM1300_GPIO_GPIINPUT	    0
33 #define NPM1300_GPIO_GPILOGIC1	    1
34 #define NPM1300_GPIO_GPILOGIC0	    2
35 #define NPM1300_GPIO_GPIEVENTRISE   3
36 #define NPM1300_GPIO_GPIEVENTFALL   4
37 #define NPM1300_GPIO_GPOIRQ	    5
38 #define NPM1300_GPIO_GPORESET	    6
39 #define NPM1300_GPIO_GPOPWRLOSSWARN 7
40 #define NPM1300_GPIO_GPOLOGIC1	    8
41 #define NPM1300_GPIO_GPOLOGIC0	    9
42 
43 struct gpio_npm1300_config {
44 	struct gpio_driver_config common;
45 	const struct device *mfd;
46 };
47 
48 struct gpio_npm1300_data {
49 	struct gpio_driver_data common;
50 };
51 
gpio_npm1300_port_get_raw(const struct device * dev,uint32_t * value)52 static int gpio_npm1300_port_get_raw(const struct device *dev, uint32_t *value)
53 {
54 	const struct gpio_npm1300_config *config = dev->config;
55 	int ret;
56 	uint8_t data;
57 
58 	ret = mfd_npm1300_reg_read(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_STATUS, &data);
59 
60 	if (ret < 0) {
61 		return ret;
62 	}
63 
64 	*value = data;
65 
66 	return 0;
67 }
68 
gpio_npm1300_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)69 static int gpio_npm1300_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
70 					    gpio_port_value_t value)
71 {
72 	const struct gpio_npm1300_config *config = dev->config;
73 	int ret = 0;
74 
75 	for (size_t idx = 0; idx < NPM1300_GPIO_PINS; idx++) {
76 		if ((mask & BIT(idx)) != 0U) {
77 			if ((value & BIT(idx)) != 0U) {
78 				ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE,
79 							    NPM_GPIO_OFFSET_MODE + idx,
80 							    NPM1300_GPIO_GPOLOGIC1);
81 			} else {
82 				ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE,
83 							    NPM_GPIO_OFFSET_MODE + idx,
84 							    NPM1300_GPIO_GPOLOGIC0);
85 			}
86 			if (ret != 0U) {
87 				return ret;
88 			}
89 		}
90 	}
91 
92 	return ret;
93 }
94 
gpio_npm1300_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)95 static int gpio_npm1300_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
96 {
97 	return gpio_npm1300_port_set_masked_raw(dev, pins, pins);
98 }
99 
gpio_npm1300_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)100 static int gpio_npm1300_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
101 {
102 	return gpio_npm1300_port_set_masked_raw(dev, pins, 0U);
103 }
104 
gpio_npm1300_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)105 static inline int gpio_npm1300_configure(const struct device *dev, gpio_pin_t pin,
106 					 gpio_flags_t flags)
107 {
108 	const struct gpio_npm1300_config *config = dev->config;
109 	int ret = 0;
110 
111 	if (k_is_in_isr()) {
112 		return -EWOULDBLOCK;
113 	}
114 
115 	if (pin >= NPM1300_GPIO_PINS) {
116 		return -EINVAL;
117 	}
118 
119 	/* Configure mode */
120 	if ((flags & GPIO_INPUT) != 0U) {
121 		if (flags & GPIO_ACTIVE_LOW) {
122 			ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE,
123 						    NPM_GPIO_OFFSET_MODE + pin,
124 						    NPM1300_GPIO_GPIEVENTFALL);
125 		} else {
126 			ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE,
127 						    NPM_GPIO_OFFSET_MODE + pin,
128 						    NPM1300_GPIO_GPIEVENTRISE);
129 		}
130 	} else if ((flags & NPM1300_GPIO_WDT_RESET_ON) != 0U) {
131 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
132 					    NPM1300_GPIO_GPORESET);
133 	} else if ((flags & NPM1300_GPIO_PWRLOSSWARN_ON) != 0U) {
134 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
135 					    NPM1300_GPIO_GPOPWRLOSSWARN);
136 	} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
137 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
138 					    NPM1300_GPIO_GPOLOGIC1);
139 	} else if ((flags & GPIO_OUTPUT) != 0U) {
140 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
141 					    NPM1300_GPIO_GPOLOGIC0);
142 	}
143 
144 	if (ret < 0) {
145 		return ret;
146 	}
147 
148 	/* Configure open drain */
149 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_OPENDRAIN + pin,
150 				    !!(flags & GPIO_SINGLE_ENDED));
151 	if (ret < 0) {
152 		return ret;
153 	}
154 
155 	/* Configure pulls */
156 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLUP + pin,
157 				    !!(flags & GPIO_PULL_UP));
158 	if (ret < 0) {
159 		return ret;
160 	}
161 
162 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLDOWN + pin,
163 				    !!(flags & GPIO_PULL_DOWN));
164 	if (ret < 0) {
165 		return ret;
166 	}
167 
168 	/* Configure drive strength and debounce */
169 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DRIVE + pin,
170 				    !!(flags & NPM1300_GPIO_DRIVE_6MA));
171 	if (ret < 0) {
172 		return ret;
173 	}
174 
175 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin,
176 				    !!(flags & NPM1300_GPIO_DEBOUNCE_ON));
177 
178 	return ret;
179 }
180 
gpio_npm1300_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)181 static int gpio_npm1300_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
182 {
183 	int ret;
184 	uint32_t value;
185 
186 	ret = gpio_npm1300_port_get_raw(dev, &value);
187 
188 	if (ret < 0) {
189 		return ret;
190 	}
191 
192 	return gpio_npm1300_port_set_masked_raw(dev, pins, ~value);
193 }
194 
195 static DEVICE_API(gpio, gpio_npm1300_api) = {
196 	.pin_configure = gpio_npm1300_configure,
197 	.port_get_raw = gpio_npm1300_port_get_raw,
198 	.port_set_masked_raw = gpio_npm1300_port_set_masked_raw,
199 	.port_set_bits_raw = gpio_npm1300_port_set_bits_raw,
200 	.port_clear_bits_raw = gpio_npm1300_port_clear_bits_raw,
201 	.port_toggle_bits = gpio_npm1300_port_toggle_bits,
202 };
203 
gpio_npm1300_init(const struct device * dev)204 static int gpio_npm1300_init(const struct device *dev)
205 {
206 	const struct gpio_npm1300_config *config = dev->config;
207 
208 	if (!device_is_ready(config->mfd)) {
209 		return -ENODEV;
210 	}
211 
212 	return 0;
213 }
214 
215 #define GPIO_NPM1300_DEFINE(n)                                                                     \
216 	static const struct gpio_npm1300_config gpio_npm1300_config##n = {                         \
217 		.common =                                                                          \
218 			{                                                                          \
219 				.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),               \
220 			},                                                                         \
221 		.mfd = DEVICE_DT_GET(DT_INST_PARENT(n))};                                          \
222                                                                                                    \
223 		static struct gpio_npm1300_data gpio_npm1300_data##n;                              \
224                                                                                                    \
225 	DEVICE_DT_INST_DEFINE(n, gpio_npm1300_init, NULL, &gpio_npm1300_data##n,                   \
226 			      &gpio_npm1300_config##n, POST_KERNEL,                                \
227 			      CONFIG_GPIO_NPM1300_INIT_PRIORITY, &gpio_npm1300_api);
228 
229 DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1300_DEFINE)
230