1 /*
2  * Copyright (c) 2021, Yonatan Schachter
3  * Copyright (c) 2025, Andrew Featherstone
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/irq.h>
11 
12 /* pico-sdk includes */
13 #include <hardware/gpio.h>
14 #include <hardware/regs/intctrl.h>
15 #include <hardware/structs/iobank0.h>
16 
17 #include <zephyr/drivers/gpio/gpio_utils.h>
18 
19 #define DT_DRV_COMPAT raspberrypi_pico_gpio_port
20 
21 #define ALL_EVENTS (GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE \
22 		| GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH)
23 
24 #define GPIO_RPI_PINS_PER_PORT 32
25 
26 #define ADDR_IS_ZERO(n, x)     (DT_INST_REG_ADDR(n) == 0) |
27 #define ADDR_IS_NON_ZERO(n, x) (DT_INST_REG_ADDR(n) != 0) |
28 #define GPIO_RPI_LO_AVAILABLE  (DT_INST_FOREACH_STATUS_OKAY_VARGS(ADDR_IS_ZERO) 0)
29 #define GPIO_RPI_HI_AVAILABLE  (DT_INST_FOREACH_STATUS_OKAY_VARGS(ADDR_IS_NON_ZERO) 0)
30 
31 #if GPIO_RPI_HI_AVAILABLE
32 #define PORT_NO(port) ((((struct gpio_rpi_config *)port->config)->high_dev != NULL) ? 0 : 1)
33 #else
34 #define PORT_NO(port) ((int)port & 0) /* generate zero and suppress unused warning */
35 #endif
36 
37 struct gpio_rpi_config {
38 	struct gpio_driver_config common;
39 	void (*bank_config_func)(void);
40 #if GPIO_RPI_HI_AVAILABLE
41 	const struct device *high_dev;
42 #endif
43 };
44 
45 struct gpio_rpi_data {
46 	struct gpio_driver_data common;
47 	sys_slist_t callbacks;
48 	uint32_t single_ended_mask;
49 	uint32_t open_drain_mask;
50 };
51 
gpio_set_dir_out_masked_n(uint n,uint32_t mask)52 static inline void gpio_set_dir_out_masked_n(uint n, uint32_t mask)
53 {
54 	if (!n) {
55 		gpio_set_dir_out_masked(mask);
56 	} else if (n == 1) {
57 #if PICO_USE_GPIO_COPROCESSOR
58 		gpioc_hi_oe_set(mask);
59 #else
60 		sio_hw->gpio_hi_oe_set = mask;
61 #endif
62 	}
63 }
64 
gpio_set_dir_in_masked_n(uint n,uint32_t mask)65 static inline void gpio_set_dir_in_masked_n(uint n, uint32_t mask)
66 {
67 	if (!n) {
68 		gpio_set_dir_in_masked(mask);
69 	} else if (n == 1) {
70 #if PICO_USE_GPIO_COPROCESSOR
71 		gpioc_hi_oe_clr(mask);
72 #else
73 		sio_hw->gpio_hi_oe_clr = mask;
74 #endif
75 	}
76 }
77 
gpio_set_dir_masked_n(uint n,uint32_t mask,uint32_t value)78 static inline void gpio_set_dir_masked_n(uint n, uint32_t mask, uint32_t value)
79 {
80 	if (!n) {
81 		gpio_set_dir_masked(mask, value);
82 	} else if (n == 1) {
83 #if PICO_USE_GPIO_COPROCESSOR
84 		gpioc_hi_oe_xor((gpioc_hi_oe_get() ^ value) & mask);
85 #else
86 		sio_hw->gpio_oe_togl = (sio_hw->gpio_hi_oe ^ value) & mask;
87 #endif
88 	}
89 }
90 
gpio_get_all_n(uint n)91 static inline uint32_t gpio_get_all_n(uint n)
92 {
93 	if (!n) {
94 		return gpio_get_all();
95 	} else if (n == 1) {
96 #if PICO_USE_GPIO_COPROCESSOR
97 		return gpioc_hi_in_get();
98 #else
99 		return sio_hw->gpio_hi_in;
100 #endif
101 	}
102 
103 	return 0;
104 }
105 
gpio_toggle_dir_masked_n(uint n,uint32_t mask)106 static inline void gpio_toggle_dir_masked_n(uint n, uint32_t mask)
107 {
108 	if (!n) {
109 #if PICO_USE_GPIO_COPROCESSOR
110 		gpioc_lo_oe_xor(mask);
111 #else
112 		sio_hw->gpio_oe_togl = mask;
113 #endif
114 	} else if (n == 1) {
115 #if PICO_USE_GPIO_COPROCESSOR
116 		gpioc_hi_oe_xor(mask);
117 #else
118 		sio_hw->gpio_hi_oe_togl = mask;
119 #endif
120 	}
121 }
122 
gpio_rpi_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)123 static int gpio_rpi_configure(const struct device *dev,
124 				gpio_pin_t pin,
125 				gpio_flags_t flags)
126 {
127 	const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev);
128 	struct gpio_rpi_data *data = dev->data;
129 
130 	if (flags == GPIO_DISCONNECTED) {
131 		gpio_disable_pulls(pin);
132 		/* This is almost the opposite of the Pico SDK's gpio_set_function. */
133 		hw_write_masked(&pads_bank0_hw->io[pin], PADS_BANK0_GPIO0_OD_BITS,
134 				PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
135 #ifdef SOC_SERIES_RP2350
136 		hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
137 #endif
138 		return 0;
139 	}
140 
141 	gpio_set_pulls(pin + offset, (flags & GPIO_PULL_UP) != 0U, (flags & GPIO_PULL_DOWN) != 0U);
142 
143 	/* Avoid gpio_init, since that also clears previously set direction/high/low */
144 	gpio_set_function(pin + offset, GPIO_FUNC_SIO);
145 
146 	if (flags & GPIO_INPUT) {
147 		gpio_set_dir(pin + offset, GPIO_IN);
148 	} else {
149 		gpio_set_input_enabled(pin + offset, false);
150 	}
151 
152 	if (flags & GPIO_OUTPUT) {
153 		if (flags & GPIO_SINGLE_ENDED) {
154 			data->single_ended_mask |= BIT(pin);
155 
156 			/* Setting the initial state of output data, and output enable.
157 			 * The output data will not change from here on, only output
158 			 * enable will. If none of the GPIO_OUTPUT_INIT_* flags have
159 			 * been set then fall back to the non-agressive input mode.
160 			 */
161 			if (flags & GPIO_LINE_OPEN_DRAIN) {
162 				data->open_drain_mask |= BIT(pin);
163 				gpio_put(pin + offset, 0);
164 				gpio_set_dir(pin + offset, flags & GPIO_OUTPUT_INIT_LOW);
165 			} else {
166 				data->open_drain_mask &= ~(BIT(pin));
167 				gpio_put(pin + offset, 1);
168 				gpio_set_dir(pin + offset, flags & GPIO_OUTPUT_INIT_HIGH);
169 			}
170 		} else {
171 			data->single_ended_mask &= ~(BIT(pin));
172 			if (flags & GPIO_OUTPUT_INIT_HIGH) {
173 				gpio_put(pin + offset, 1);
174 			} else if (flags & GPIO_OUTPUT_INIT_LOW) {
175 				gpio_put(pin + offset, 0);
176 			}
177 			gpio_set_dir(pin + offset, GPIO_OUT);
178 		}
179 	}
180 
181 	return 0;
182 }
183 
184 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_rpi_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * flags)185 static int gpio_rpi_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags)
186 {
187 	const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev);
188 	struct gpio_rpi_data *data = dev->data;
189 
190 	*flags = 0;
191 
192 	/* RP2xxxx supports Bus Keeper mode where both pull-up and pull-down are enabled. */
193 	if (gpio_is_pulled_up(pin + offset)) {
194 		*flags |= GPIO_PULL_UP;
195 	}
196 	if (gpio_is_pulled_down(pin + offset)) {
197 		*flags |= GPIO_PULL_DOWN;
198 	}
199 
200 	if (gpio_get_dir(pin + offset)) {
201 		*flags |= gpio_get_out_level(pin + offset) ? GPIO_OUTPUT_HIGH : GPIO_OUTPUT_LOW;
202 		if (data->single_ended_mask & BIT(pin)) {
203 			*flags |=
204 				data->open_drain_mask & BIT(pin) ? GPIO_OPEN_DRAIN : GPIO_PUSH_PULL;
205 		}
206 	}
207 
208 	if (pads_bank0_hw->io[pin] & PADS_BANK0_GPIO0_IE_BITS) {
209 		*flags |= GPIO_INPUT;
210 	}
211 
212 	return 0;
213 }
214 #endif
215 
gpio_rpi_port_get_raw(const struct device * port,uint32_t * value)216 static int gpio_rpi_port_get_raw(const struct device *port, uint32_t *value)
217 {
218 	*value = gpio_get_all_n(PORT_NO(port));
219 
220 	return 0;
221 }
222 
gpio_rpi_port_set_masked_raw(const struct device * port,uint32_t mask,uint32_t value)223 static int gpio_rpi_port_set_masked_raw(const struct device *port,
224 					uint32_t mask, uint32_t value)
225 {
226 	struct gpio_rpi_data *data = port->data;
227 
228 	/* First handle push-pull pins: */
229 	gpio_put_masked_n(PORT_NO(port), mask & ~data->single_ended_mask, value);
230 	/* Then handle open-drain pins: */
231 	gpio_set_dir_masked_n(PORT_NO(port), mask & data->single_ended_mask & data->open_drain_mask,
232 			      ~value);
233 	/* Then handle open-source pins: */
234 	gpio_set_dir_masked_n(PORT_NO(port),
235 			      mask & data->single_ended_mask & ~data->open_drain_mask, value);
236 
237 	return 0;
238 }
239 
gpio_rpi_port_set_bits_raw(const struct device * port,uint32_t pins)240 static int gpio_rpi_port_set_bits_raw(const struct device *port,
241 					uint32_t pins)
242 {
243 	struct gpio_rpi_data *data = port->data;
244 
245 	/* First handle push-pull pins: */
246 	gpio_set_mask_n(PORT_NO(port), pins & ~data->single_ended_mask);
247 	/* Then handle open-drain pins: */
248 	gpio_set_dir_in_masked_n(PORT_NO(port),
249 				 pins & data->single_ended_mask & data->open_drain_mask);
250 	/* Then handle open-source pins: */
251 	gpio_set_dir_out_masked_n(PORT_NO(port),
252 				  pins & data->single_ended_mask & ~data->open_drain_mask);
253 
254 	return 0;
255 }
256 
gpio_rpi_port_clear_bits_raw(const struct device * port,uint32_t pins)257 static int gpio_rpi_port_clear_bits_raw(const struct device *port,
258 					uint32_t pins)
259 {
260 	struct gpio_rpi_data *data = port->data;
261 
262 	/* First handle push-pull pins: */
263 	gpio_clr_mask_n(PORT_NO(port), pins & ~data->single_ended_mask);
264 	/* Then handle open-drain pins: */
265 	gpio_set_dir_out_masked_n(PORT_NO(port),
266 				  pins & data->single_ended_mask & data->open_drain_mask);
267 	/* Then handle open-source pins: */
268 	gpio_set_dir_in_masked_n(PORT_NO(port),
269 				 pins & data->single_ended_mask & ~data->open_drain_mask);
270 
271 	return 0;
272 }
273 
gpio_rpi_port_toggle_bits(const struct device * port,uint32_t pins)274 static int gpio_rpi_port_toggle_bits(const struct device *port,
275 					uint32_t pins)
276 {
277 	struct gpio_rpi_data *data = port->data;
278 
279 	/* First handle push-pull pins: */
280 	gpio_xor_mask_n(PORT_NO(port), pins & ~data->single_ended_mask);
281 	/* Then handle single-ended pins: */
282 	gpio_toggle_dir_masked_n(PORT_NO(port), pins & data->single_ended_mask);
283 
284 	return 0;
285 }
286 
gpio_rpi_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)287 static int gpio_rpi_pin_interrupt_configure(const struct device *dev,
288 						gpio_pin_t pin,
289 						enum gpio_int_mode mode,
290 						enum gpio_int_trig trig)
291 {
292 	const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev);
293 	uint32_t events = 0;
294 
295 	gpio_set_irq_enabled(pin + offset, ALL_EVENTS, false);
296 	if (mode != GPIO_INT_DISABLE) {
297 		if (mode & GPIO_INT_EDGE) {
298 			if (trig & GPIO_INT_LOW_0) {
299 				events |= GPIO_IRQ_EDGE_FALL;
300 			}
301 			if (trig & GPIO_INT_HIGH_1) {
302 				events |= GPIO_IRQ_EDGE_RISE;
303 			}
304 		} else {
305 			if (trig & GPIO_INT_LOW_0) {
306 				events |= GPIO_IRQ_LEVEL_LOW;
307 			}
308 			if (trig & GPIO_INT_HIGH_1) {
309 				events |= GPIO_IRQ_LEVEL_HIGH;
310 			}
311 		}
312 		gpio_set_irq_enabled(pin + offset, events, true);
313 	}
314 
315 	return 0;
316 }
317 
gpio_rpi_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)318 static int gpio_rpi_manage_callback(const struct device *dev,
319 				struct gpio_callback *callback, bool set)
320 {
321 	struct gpio_rpi_data *data = dev->data;
322 
323 	return gpio_manage_callback(&data->callbacks, callback, set);
324 }
325 
gpio_rpi_get_pending_int(const struct device * dev)326 static uint32_t gpio_rpi_get_pending_int(const struct device *dev)
327 {
328 	io_bank0_irq_ctrl_hw_t *irq_ctrl_base =
329 		get_core_num() ? &io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw->proc0_irq_ctrl;
330 	ARRAY_FOR_EACH_PTR(irq_ctrl_base->ints, p) {
331 		if (*p) {
332 			return 1;
333 		}
334 	}
335 
336 	return 0;
337 }
338 
339 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_rpi_port_get_direction(const struct device * port,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)340 static int gpio_rpi_port_get_direction(const struct device *port, gpio_port_pins_t map,
341 				  gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
342 {
343 	/* The Zephyr API considers a disconnected pin to be neither an input nor output.
344 	 * Since we disable both OE and IE for disconnected pins clear the mask bits.
345 	 */
346 	for (int pin = 0; pin < NUM_BANK0_GPIOS; pin++) {
347 		if (pads_bank0_hw->io[pin] & PADS_BANK0_GPIO0_OD_BITS) {
348 			map &= ~BIT(pin);
349 		}
350 		if (inputs && (pads_bank0_hw->io[pin] & PADS_BANK0_GPIO0_IE_BITS)) {
351 			*inputs |= BIT(pin);
352 		}
353 	}
354 	if (inputs) {
355 		*inputs &= map;
356 	}
357 	if (outputs) {
358 		*outputs = sio_hw->gpio_oe & map;
359 	}
360 
361 	return 0;
362 }
363 #endif
364 
365 static DEVICE_API(gpio, gpio_rpi_driver_api) = {
366 	.pin_configure = gpio_rpi_configure,
367 #ifdef CONFIG_GPIO_GET_CONFIG
368 	.pin_get_config = gpio_rpi_get_config,
369 #endif
370 	.port_get_raw = gpio_rpi_port_get_raw,
371 	.port_set_masked_raw = gpio_rpi_port_set_masked_raw,
372 	.port_set_bits_raw = gpio_rpi_port_set_bits_raw,
373 	.port_clear_bits_raw = gpio_rpi_port_clear_bits_raw,
374 	.port_toggle_bits = gpio_rpi_port_toggle_bits,
375 	.pin_interrupt_configure = gpio_rpi_pin_interrupt_configure,
376 	.manage_callback = gpio_rpi_manage_callback,
377 	.get_pending_int = gpio_rpi_get_pending_int,
378 #ifdef CONFIG_GPIO_GET_DIRECTION
379 	.port_get_direction = gpio_rpi_port_get_direction,
380 #endif
381 };
382 
gpio_rpi_isr(const struct device * dev)383 static void gpio_rpi_isr(const struct device *dev)
384 {
385 	struct gpio_rpi_data *data = dev->data;
386 	io_bank0_irq_ctrl_hw_t *irq_ctrl_base;
387 	const io_rw_32 *status_reg;
388 	uint32_t events;
389 	uint32_t pin;
390 
391 	irq_ctrl_base = &iobank0_hw->proc0_irq_ctrl;
392 	for (pin = 0; pin < NUM_BANK0_GPIOS; pin++) {
393 		status_reg = &irq_ctrl_base->ints[pin / 8];
394 		events = (*status_reg >> 4 * (pin % 8)) & ALL_EVENTS;
395 		if (events) {
396 			gpio_acknowledge_irq(pin, ALL_EVENTS);
397 
398 #if GPIO_RPI_HI_AVAILABLE
399 			if (pin >= GPIO_RPI_PINS_PER_PORT) {
400 				const struct gpio_rpi_config *config = dev->config;
401 				struct gpio_rpi_data *high_data = config->high_dev->data;
402 
403 				gpio_fire_callbacks(&high_data->callbacks, config->high_dev,
404 						    BIT(pin - GPIO_RPI_PINS_PER_PORT));
405 				continue;
406 			}
407 #endif
408 
409 			gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
410 		}
411 	}
412 }
413 
gpio_rpi_bank_init(const struct device * dev)414 static int gpio_rpi_bank_init(const struct device *dev)
415 {
416 	const struct gpio_rpi_config *config = dev->config;
417 
418 	if (config->bank_config_func != NULL) {
419 		config->bank_config_func();
420 	}
421 
422 	return 0;
423 }
424 
425 #define GPIO_REG_0U            1
426 #define IS_GPIO_RPI_LO_NODE(n) UTIL_CAT(GPIO_REG_, DT_REG_ADDR(n))
427 
428 #define DEVICE_IF_GPIO_RPI_HI_NODE(n) COND_CODE_1(IS_GPIO_RPI_LO_NODE(n), (), (DEVICE_DT_GET(n)))
429 
430 #define FIND_GPIO_RPI_HI_DEVICE(n)                                                                 \
431 	COND_CODE_1(UTIL_CAT(GPIO_REG_, DT_REG_ADDR(n)),                                           \
432 			(DT_FOREACH_CHILD(DT_PARENT(n), DEVICE_IF_GPIO_RPI_HI_NODE)), (NULL))
433 
434 #if GPIO_RPI_HI_AVAILABLE
435 #define GPIO_RPI_INIT_HIGH_DEV(idx) .high_dev = FIND_GPIO_RPI_HI_DEVICE(DT_DRV_INST(idx)),
436 #else
437 #define GPIO_RPI_INIT_HIGH_DEV(idx)
438 #endif
439 
440 #define GPIO_RPI_INIT(idx)                                                                         \
441 	BUILD_ASSERT(DT_CHILD_NUM(DT_INST_PARENT(idx)) > 0 &&                                      \
442 			     DT_CHILD_NUM(DT_INST_PARENT(idx)) <= 2,                               \
443 		     "raspberrypi,pico-gpio node must have one or two child node.");               \
444 	BUILD_ASSERT(GPIO_RPI_LO_AVAILABLE,                                                        \
445 		     "raspberrypi,pico-gpio node must have reg=0 child node.");                    \
446 	IF_ENABLED(IS_GPIO_RPI_LO_NODE(DT_DRV_INST(idx)), (                                        \
447 		static void bank_##idx##_config_func(void)                                         \
448 		{                                                                                  \
449 			IRQ_CONNECT(DT_IRQN(DT_INST_PARENT(idx)),                                  \
450 				    DT_IRQ(DT_INST_PARENT(idx), priority),                         \
451 				    gpio_rpi_isr, DEVICE_DT_INST_GET(idx), 0);                     \
452 			irq_enable(DT_IRQN(DT_INST_PARENT(idx)));                                  \
453 		}                                                                                  \
454 	))                                                                                         \
455 	static const struct gpio_rpi_config gpio_rpi_##idx##_config = {                            \
456 		.common = {                                                                        \
457 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx),                     \
458 		},                                                                                 \
459 		IF_ENABLED(IS_GPIO_RPI_LO_NODE(DT_DRV_INST(idx)), (                                \
460 			.bank_config_func = bank_##idx##_config_func,                              \
461 		))                                                                                 \
462 		GPIO_RPI_INIT_HIGH_DEV(idx)                                                        \
463 	};                                                                                         \
464 	static struct gpio_rpi_data gpio_rpi_##idx##_data;                                         \
465                                                                                                    \
466 	DEVICE_DT_INST_DEFINE(idx, gpio_rpi_bank_init, NULL, &gpio_rpi_##idx##_data,               \
467 			      &gpio_rpi_##idx##_config, POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY,    \
468 			      &gpio_rpi_driver_api);
469 
470 DT_INST_FOREACH_STATUS_OKAY(GPIO_RPI_INIT)
471