1 /*
2 * Copyright (c) 2023 Frontgrade Gaisler AB
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * Driver for GRLIB GRGPIO revision 2.
9 * - iflag determine pending interrupt.
10 * - interrupt map decides interrupt number if implemented.
11 * - logic or/and/xor registers used when possible
12 */
13
14 #define DT_DRV_COMPAT gaisler_grgpio
15
16 #include <zephyr/kernel.h>
17 #include <zephyr/drivers/gpio.h>
18 #include <zephyr/drivers/gpio/gpio_utils.h>
19 #include "gpio_grgpio.h"
20
21 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(gpio_grgpio2);
24
25 struct cfg {
26 struct gpio_driver_config common;
27 volatile struct grgpio_regs *regs;
28 int interrupt;
29 };
30
31 struct data {
32 struct gpio_driver_data common;
33 struct k_spinlock lock;
34 sys_slist_t cb;
35 uint32_t imask;
36 uint32_t connected;
37 int irqgen;
38 };
39
40 static void grgpio_isr(const struct device *dev);
41
pin_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)42 static int pin_configure(const struct device *dev,
43 gpio_pin_t pin, gpio_flags_t flags)
44 {
45 const struct cfg *cfg = dev->config;
46 struct data *data = dev->data;
47 volatile struct grgpio_regs *regs = cfg->regs;
48 uint32_t mask = 1 << pin;
49
50 if (flags & GPIO_SINGLE_ENDED) {
51 return -ENOTSUP;
52 }
53
54 if (flags == GPIO_DISCONNECTED) {
55 return -ENOTSUP;
56 }
57
58 if ((flags & GPIO_DIR_MASK) == (GPIO_INPUT | GPIO_OUTPUT)) {
59 return -ENOTSUP;
60 }
61
62 if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
63 return -ENOTSUP;
64 }
65
66 if (flags & GPIO_OUTPUT) {
67 k_spinlock_key_t key;
68
69 /*
70 * Register operations are atomic, but do the sequence under
71 * lock so it serializes.
72 */
73 key = k_spin_lock(&data->lock);
74 if (flags & GPIO_OUTPUT_INIT_HIGH) {
75 regs->output_or = mask;
76 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
77 regs->output_and = ~mask;
78 }
79 regs->dir_or = mask;
80 k_spin_unlock(&data->lock, key);
81 } else {
82 regs->dir_and = ~mask;
83 }
84
85 return 0;
86 }
87
port_get_raw(const struct device * dev,gpio_port_value_t * value)88 static int port_get_raw(const struct device *dev, gpio_port_value_t *value)
89 {
90 const struct cfg *cfg = dev->config;
91
92 *value = cfg->regs->data;
93 return 0;
94 }
95
port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)96 static int port_set_masked_raw(const struct device *dev,
97 gpio_port_pins_t mask,
98 gpio_port_value_t value)
99 {
100 const struct cfg *cfg = dev->config;
101 struct data *data = dev->data;
102 volatile struct grgpio_regs *regs = cfg->regs;
103 uint32_t port_val;
104 k_spinlock_key_t key;
105
106 value &= mask;
107 key = k_spin_lock(&data->lock);
108 port_val = (regs->output & ~mask) | value;
109 regs->output = port_val;
110 k_spin_unlock(&data->lock, key);
111
112 return 0;
113 }
114
port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)115 static int port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
116 {
117 const struct cfg *cfg = dev->config;
118 volatile struct grgpio_regs *regs = cfg->regs;
119
120 regs->output_or = pins;
121 return 0;
122 }
123
port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)124 static int port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
125 {
126 const struct cfg *cfg = dev->config;
127 volatile struct grgpio_regs *regs = cfg->regs;
128
129 regs->output_and = ~pins;
130 return 0;
131 }
132
port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)133 static int port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
134 {
135 const struct cfg *cfg = dev->config;
136 volatile struct grgpio_regs *regs = cfg->regs;
137
138 regs->output_xor = pins;
139 return 0;
140 }
141
get_pending_int(const struct device * dev)142 static uint32_t get_pending_int(const struct device *dev)
143 {
144 const struct cfg *cfg = dev->config;
145 volatile struct grgpio_regs *regs = cfg->regs;
146
147 return regs->iflag;
148 }
149
pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)150 static int pin_interrupt_configure(const struct device *dev,
151 gpio_pin_t pin,
152 enum gpio_int_mode mode,
153 enum gpio_int_trig trig)
154 {
155 const struct cfg *cfg = dev->config;
156 struct data *data = dev->data;
157 volatile struct grgpio_regs *regs = cfg->regs;
158 int ret = 0;
159 const uint32_t mask = 1 << pin;
160 uint32_t polmask;
161 k_spinlock_key_t key;
162
163 if ((mask & data->imask) == 0) {
164 /* This pin can not generate interrupt */
165 return -ENOTSUP;
166 }
167 if (mode != GPIO_INT_MODE_DISABLED) {
168 if (trig == GPIO_INT_TRIG_LOW) {
169 polmask = 0;
170 } else if (trig == GPIO_INT_TRIG_HIGH) {
171 polmask = mask;
172 } else {
173 return -ENOTSUP;
174 }
175 }
176 key = k_spin_lock(&data->lock);
177 if (mode == GPIO_INT_MODE_DISABLED) {
178 regs->imask_and = ~mask;
179 } else if (mode == GPIO_INT_MODE_LEVEL) {
180 regs->imask_and = ~mask;
181 regs->iedge &= ~mask;
182 regs->ipol = (regs->ipol & ~mask) | polmask;
183 regs->imask_or = mask;
184 } else if (mode == GPIO_INT_MODE_EDGE) {
185 regs->imask_and = ~mask;
186 regs->iedge |= mask;
187 regs->ipol = (regs->ipol & ~mask) | polmask;
188 regs->imask_or = mask;
189 } else {
190 ret = -ENOTSUP;
191 }
192 k_spin_unlock(&data->lock, key);
193
194 /* Remove old interrupt history for this pin. */
195 regs->iflag = mask;
196
197 int interrupt = cfg->interrupt;
198 const int irqgen = data->irqgen;
199
200 if (irqgen == 0) {
201 interrupt += pin;
202 } else if (irqgen == 1) {
203 ;
204 } else if (irqgen < 32) {
205 /* look up interrupt number in GRGPIO interrupt map */
206 uint32_t val = regs->irqmap[pin/4];
207
208 val >>= (3 - pin % 4) * 8;
209 interrupt += (val & 0x1f);
210 }
211
212 if (interrupt && ((1 << interrupt) & data->connected) == 0) {
213 irq_connect_dynamic(
214 interrupt,
215 0,
216 (void (*)(const void *)) grgpio_isr,
217 dev,
218 0
219 );
220 irq_enable(interrupt);
221 data->connected |= 1 << interrupt;
222 }
223
224 return ret;
225 }
226
manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)227 static int manage_callback(const struct device *dev,
228 struct gpio_callback *callback,
229 bool set)
230 {
231 struct data *data = dev->data;
232
233 return gpio_manage_callback(&data->cb, callback, set);
234 }
235
grgpio_isr(const struct device * dev)236 static void grgpio_isr(const struct device *dev)
237 {
238 const struct cfg *cfg = dev->config;
239 struct data *data = dev->data;
240 volatile struct grgpio_regs *regs = cfg->regs;
241 uint32_t pins;
242
243 /* no locking needed when iflag is implemented */
244 pins = regs->iflag;
245 if (pins == 0) {
246 return;
247 }
248 regs->iflag = pins;
249 gpio_fire_callbacks(&data->cb, dev, pins);
250 }
251
grgpio_init(const struct device * dev)252 static int grgpio_init(const struct device *dev)
253 {
254 const struct cfg *cfg = dev->config;
255 struct data *data = dev->data;
256 volatile struct grgpio_regs *regs = cfg->regs;
257
258 data->irqgen = (regs->cap & GRGPIO_CAP_IRQGEN) >> GRGPIO_CAP_IRQGEN_BIT;
259 regs->dir = 0;
260 /* Mask all Interrupts */
261 regs->imask = 0;
262 /* Make IRQ Rising edge triggered default */
263 regs->ipol = 0xffffffff;
264 regs->iedge = 0xffffffff;
265 regs->iflag = 0xffffffff;
266 /* Read what I/O lines have IRQ support */
267 data->imask = regs->ipol;
268
269 return 0;
270 }
271
272 static DEVICE_API(gpio, driver_api) = {
273 .pin_configure = pin_configure,
274 .port_get_raw = port_get_raw,
275 .port_set_masked_raw = port_set_masked_raw,
276 .port_set_bits_raw = port_set_bits_raw,
277 .port_clear_bits_raw = port_clear_bits_raw,
278 .port_toggle_bits = port_toggle_bits,
279 .pin_interrupt_configure = pin_interrupt_configure,
280 .manage_callback = manage_callback,
281 .get_pending_int = get_pending_int,
282 };
283
284 #define GRGPIO_INIT(n) \
285 static const struct cfg cfg_##n = { \
286 .common = { \
287 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),\
288 }, \
289 .regs = (void *) DT_INST_REG_ADDR(n), \
290 .interrupt = DT_INST_IRQN(n), \
291 }; \
292 static struct data data_##n; \
293 \
294 DEVICE_DT_INST_DEFINE(n, \
295 grgpio_init, \
296 NULL, \
297 &data_##n, \
298 &cfg_##n, \
299 POST_KERNEL, \
300 CONFIG_GPIO_INIT_PRIORITY, \
301 &driver_api \
302 );
303
304 DT_INST_FOREACH_STATUS_OKAY(GRGPIO_INIT)
305