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 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
122 					    NPM1300_GPIO_GPIINPUT);
123 	} else if ((flags & NPM1300_GPIO_WDT_RESET_ON) != 0U) {
124 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
125 					    NPM1300_GPIO_GPORESET);
126 	} else if ((flags & NPM1300_GPIO_PWRLOSSWARN_ON) != 0U) {
127 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
128 					    NPM1300_GPIO_GPOPWRLOSSWARN);
129 	} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
130 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
131 					    NPM1300_GPIO_GPOLOGIC1);
132 	} else if ((flags & GPIO_OUTPUT) != 0U) {
133 		ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin,
134 					    NPM1300_GPIO_GPOLOGIC0);
135 	}
136 
137 	if (ret < 0) {
138 		return ret;
139 	}
140 
141 	/* Configure open drain */
142 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_OPENDRAIN + pin,
143 				    !!(flags & GPIO_SINGLE_ENDED));
144 	if (ret < 0) {
145 		return ret;
146 	}
147 
148 	/* Configure pulls */
149 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLUP + pin,
150 				    !!(flags & GPIO_PULL_UP));
151 	if (ret < 0) {
152 		return ret;
153 	}
154 
155 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLDOWN + pin,
156 				    !!(flags & GPIO_PULL_DOWN));
157 	if (ret < 0) {
158 		return ret;
159 	}
160 
161 	/* Configure drive strength and debounce */
162 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DRIVE + pin,
163 				    !!(flags & NPM1300_GPIO_DRIVE_6MA));
164 	if (ret < 0) {
165 		return ret;
166 	}
167 
168 	ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin,
169 				    !!(flags & NPM1300_GPIO_DEBOUNCE_ON));
170 
171 	return ret;
172 }
173 
gpio_npm1300_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)174 static int gpio_npm1300_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
175 {
176 	int ret;
177 	uint32_t value;
178 
179 	ret = gpio_npm1300_port_get_raw(dev, &value);
180 
181 	if (ret < 0) {
182 		return ret;
183 	}
184 
185 	return gpio_npm1300_port_set_masked_raw(dev, pins, ~value);
186 }
187 
188 static const struct gpio_driver_api gpio_npm1300_api = {
189 	.pin_configure = gpio_npm1300_configure,
190 	.port_get_raw = gpio_npm1300_port_get_raw,
191 	.port_set_masked_raw = gpio_npm1300_port_set_masked_raw,
192 	.port_set_bits_raw = gpio_npm1300_port_set_bits_raw,
193 	.port_clear_bits_raw = gpio_npm1300_port_clear_bits_raw,
194 	.port_toggle_bits = gpio_npm1300_port_toggle_bits,
195 };
196 
gpio_npm1300_init(const struct device * dev)197 static int gpio_npm1300_init(const struct device *dev)
198 {
199 	const struct gpio_npm1300_config *config = dev->config;
200 
201 	if (!device_is_ready(config->mfd)) {
202 		return -ENODEV;
203 	}
204 
205 	return 0;
206 }
207 
208 #define GPIO_NPM1300_DEFINE(n)                                                                     \
209 	static const struct gpio_npm1300_config gpio_npm1300_config##n = {                         \
210 		.common =                                                                          \
211 			{                                                                          \
212 				.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),               \
213 			},                                                                         \
214 		.mfd = DEVICE_DT_GET(DT_INST_PARENT(n))};                                          \
215                                                                                                    \
216 		static struct gpio_npm1300_data gpio_npm1300_data##n;                              \
217                                                                                                    \
218 	DEVICE_DT_INST_DEFINE(n, &gpio_npm1300_init, NULL, &gpio_npm1300_data##n,                  \
219 			      &gpio_npm1300_config##n, POST_KERNEL,                                \
220 			      CONFIG_GPIO_NPM1300_INIT_PRIORITY, &gpio_npm1300_api);
221 
222 DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1300_DEFINE)
223