Skip to content

Commit 5d49e53

Browse files
committed
drivers: gpio: Added support for raspberry pi
Added GPIO support for the RP2040 SoC. Only one core is supported. Signed-off-by: Yonatan Schachter <[email protected]>
1 parent 8cea7bc commit 5d49e53

File tree

8 files changed

+240
-0
lines changed

8 files changed

+240
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@
266266
/drivers/gpio/*eos_s3* @wtatarski @kowalewskijan @kgugala
267267
/drivers/gpio/*rcar* @julien-massot
268268
/drivers/gpio/*esp32* @glaubermaroto
269+
/drivers/gpio/*rpi_pico* @yonsch
269270
/drivers/hwinfo/ @alexanderwachter
270271
/drivers/i2c/i2c_common.c @sjg20
271272
/drivers/i2c/i2c_emul.c @sjg20

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SAM4L gpio_sam4l.c)
3030
zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c)
3131
zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c)
3232
zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c)
33+
zephyr_library_sources_ifdef(CONFIG_GPIO_RPI_PICO gpio_rpi_pico.c)
3334
zephyr_library_sources_ifdef(CONFIG_GPIO_RV32M1 gpio_rv32m1.c)
3435
zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c)
3536
zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c)

drivers/gpio/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ source "drivers/gpio/Kconfig.xec"
7777

7878
source "drivers/gpio/Kconfig.stellaris"
7979

80+
source "drivers/gpio/Kconfig.rpi_pico"
81+
8082
source "drivers/gpio/Kconfig.rv32m1"
8183

8284
source "drivers/gpio/Kconfig.lmp90xxx"

drivers/gpio/Kconfig.rpi_pico

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2021 Yonatan Schachter
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Workaround for not being able to have commas in macro arguments
5+
DT_COMPAT_RPI_PICO_GPIO := raspberrypi,pico-gpio
6+
7+
config GPIO_RPI_PICO
8+
default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_GPIO))
9+
select PICOSDK_USE_GPIO
10+
bool "Raspberry Pi Pico GPIO driver"

drivers/gpio/gpio_rpi_pico.c

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright (c) 2021, Yonatan Schachter
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <errno.h>
8+
#include <drivers/gpio.h>
9+
10+
/* pico-sdk includes */
11+
#include <hardware/gpio.h>
12+
#include <hardware/regs/intctrl.h>
13+
#include <hardware/structs/iobank0.h>
14+
15+
#include "gpio_utils.h"
16+
17+
#define DT_DRV_COMPAT raspberrypi_pico_gpio
18+
19+
#define ALL_EVENTS (GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE \
20+
| GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH)
21+
22+
struct gpio_rpi_config {
23+
struct gpio_driver_config common;
24+
void (*bank_config_func)(void);
25+
};
26+
27+
struct gpio_rpi_data {
28+
struct gpio_driver_data common;
29+
sys_slist_t callbacks;
30+
uint32_t int_enabled_mask;
31+
};
32+
33+
static int gpio_rpi_configure(const struct device *dev,
34+
gpio_pin_t pin,
35+
gpio_flags_t flags)
36+
{
37+
if (flags & GPIO_SINGLE_ENDED) {
38+
return -ENOTSUP;
39+
}
40+
41+
gpio_init(pin);
42+
43+
if (flags & GPIO_OUTPUT) {
44+
gpio_set_dir(pin, GPIO_OUT);
45+
46+
if (flags & GPIO_OUTPUT_INIT_HIGH) {
47+
gpio_put(pin, 1);
48+
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
49+
gpio_put(pin, 0);
50+
}
51+
} else if (flags & GPIO_INPUT) {
52+
gpio_set_dir(pin, GPIO_IN);
53+
if (flags & GPIO_PULL_UP) {
54+
gpio_pull_up(pin);
55+
} else if (flags & GPIO_PULL_DOWN) {
56+
gpio_pull_down(pin);
57+
}
58+
}
59+
60+
return 0;
61+
}
62+
63+
static int gpio_rpi_port_get_raw(const struct device *dev, uint32_t *value)
64+
{
65+
*value = gpio_get_all();
66+
return 0;
67+
}
68+
69+
static int gpio_rpi_port_set_masked_raw(const struct device *port,
70+
uint32_t mask, uint32_t value)
71+
{
72+
gpio_put_masked(mask, value);
73+
return 0;
74+
}
75+
76+
static int gpio_rpi_port_set_bits_raw(const struct device *port,
77+
uint32_t pins)
78+
{
79+
gpio_set_mask(pins);
80+
return 0;
81+
}
82+
83+
static int gpio_rpi_port_clear_bits_raw(const struct device *port,
84+
uint32_t pins)
85+
{
86+
gpio_clr_mask(pins);
87+
return 0;
88+
}
89+
90+
static int gpio_rpi_port_toggle_bits(const struct device *port,
91+
uint32_t pins)
92+
{
93+
gpio_xor_mask(pins);
94+
return 0;
95+
}
96+
97+
static int gpio_rpi_pin_interrupt_configure(const struct device *dev,
98+
gpio_pin_t pin,
99+
enum gpio_int_mode mode,
100+
enum gpio_int_trig trig)
101+
{
102+
struct gpio_rpi_data *data = dev->data;
103+
uint32_t events = 0;
104+
105+
if (mode != GPIO_INT_DISABLE) {
106+
if (mode & GPIO_INT_EDGE) {
107+
if (trig & GPIO_INT_LOW_0) {
108+
events |= GPIO_IRQ_EDGE_FALL;
109+
}
110+
if (trig & GPIO_INT_HIGH_1) {
111+
events |= GPIO_IRQ_EDGE_RISE;
112+
}
113+
} else {
114+
if (trig & GPIO_INT_LOW_0) {
115+
events |= GPIO_IRQ_LEVEL_LOW;
116+
}
117+
if (trig & GPIO_INT_HIGH_1) {
118+
events |= GPIO_IRQ_LEVEL_HIGH;
119+
}
120+
}
121+
gpio_set_irq_enabled(pin, events, true);
122+
}
123+
WRITE_BIT(data->int_enabled_mask, pin, mode != GPIO_INT_DISABLE);
124+
return 0;
125+
}
126+
127+
static int gpio_rpi_manage_callback(const struct device *dev,
128+
struct gpio_callback *callback, bool set)
129+
{
130+
struct gpio_rpi_data *data = dev->data;
131+
132+
return gpio_manage_callback(&data->callbacks, callback, set);
133+
}
134+
135+
static const struct gpio_driver_api gpio_rpi_driver_api = {
136+
.pin_configure = gpio_rpi_configure,
137+
.port_get_raw = gpio_rpi_port_get_raw,
138+
.port_set_masked_raw = gpio_rpi_port_set_masked_raw,
139+
.port_set_bits_raw = gpio_rpi_port_set_bits_raw,
140+
.port_clear_bits_raw = gpio_rpi_port_clear_bits_raw,
141+
.port_toggle_bits = gpio_rpi_port_toggle_bits,
142+
.pin_interrupt_configure = gpio_rpi_pin_interrupt_configure,
143+
.manage_callback = gpio_rpi_manage_callback,
144+
};
145+
146+
static void gpio_rpi_isr(const struct device *dev)
147+
{
148+
struct gpio_rpi_data *data = dev->data;
149+
io_irq_ctrl_hw_t *irq_ctrl_base;
150+
const io_rw_32 *status_reg;
151+
uint32_t events;
152+
uint32_t pin;
153+
154+
irq_ctrl_base = &iobank0_hw->proc0_irq_ctrl;
155+
for (pin = 0; pin < NUM_BANK0_GPIOS; pin++) {
156+
status_reg = &irq_ctrl_base->ints[pin / 8];
157+
events = (*status_reg >> 4 * (pin % 8)) & ALL_EVENTS;
158+
if (events) {
159+
gpio_acknowledge_irq(pin, ALL_EVENTS);
160+
gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
161+
}
162+
}
163+
}
164+
165+
static int gpio_rpi_bank_init(const struct device *dev)
166+
{
167+
const struct gpio_rpi_config *config = dev->config;
168+
169+
config->bank_config_func();
170+
return 0;
171+
}
172+
173+
#define GPIO_RPI_INIT(idx) \
174+
static void bank_##idx##_config_func(void) \
175+
{ \
176+
IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), \
177+
gpio_rpi_isr, DEVICE_DT_INST_GET(idx), 0); \
178+
irq_enable(DT_INST_IRQN(idx)); \
179+
} \
180+
static const struct gpio_rpi_config gpio_rpi_##idx##_config = { \
181+
.bank_config_func = bank_##idx##_config_func, \
182+
}; \
183+
\
184+
static struct gpio_rpi_data gpio_rpi_##idx##_data; \
185+
\
186+
DEVICE_DT_INST_DEFINE(idx, gpio_rpi_bank_init, NULL, \
187+
&gpio_rpi_##idx##_data, \
188+
&gpio_rpi_##idx##_config, \
189+
POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \
190+
&gpio_rpi_driver_api);
191+
192+
DT_INST_FOREACH_STATUS_OKAY(GPIO_RPI_INIT)

dts/arm/rpi_pico/rp2040.dtsi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <arm/armv6-m.dtsi>
8+
#include <dt-bindings/gpio/gpio.h>
89
#include <mem.h>
910

1011
#include "rpi_pico_common.dtsi"
@@ -51,6 +52,16 @@
5152
label = "PINCTRL";
5253
};
5354

55+
gpio0: gpio@40014000 {
56+
compatible = "raspberrypi,pico-gpio";
57+
reg = <0x40014000 DT_SIZE_K(4)>;
58+
interrupts = <13 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
59+
gpio-controller;
60+
#gpio-cells = <2>;
61+
label = "GPIO_0";
62+
status = "disabled";
63+
};
64+
5465
uart0: uart@40034000 {
5566
compatible = "raspberrypi,pico-uart";
5667
reg = <0x40034000 DT_SIZE_K(4)>;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2021, Yonatan Schachter
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Raspberry Pi Pico GPIO
5+
6+
compatible: "raspberrypi,pico-gpio"
7+
8+
include: [gpio-controller.yaml, base.yaml]
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
label:
15+
required: true
16+
17+
"#gpio-cells":
18+
const: 2
19+
20+
gpio-cells:
21+
- pin
22+
- flags

scripts/checkpatch/typedefsfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ k_mem_partition_attr_t
33
mbedtls_pk_context
44
z_arch_esf_t
55
pinctrl_soc_pin_t
6+
io_rw_32

0 commit comments

Comments
 (0)