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