Skip to content

Commit fa6a098

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 <yonatan.schachter@gmail.com>
1 parent fbe4c1a commit fa6a098

File tree

12 files changed

+259
-0
lines changed

12 files changed

+259
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@
255255
/drivers/gpio/*eos_s3* @wtatarski @kowalewskijan @kgugala
256256
/drivers/gpio/*rcar* @julien-massot
257257
/drivers/gpio/*esp32* @glaubermaroto
258+
/drivers/gpio/*rpi_pico* @yonsch
258259
/drivers/hwinfo/ @alexanderwachter
259260
/drivers/i2c/i2c_common.c @sjg20
260261
/drivers/i2c/i2c_emul.c @sjg20

boards/arm/raspberrypi_pico/doc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@ hardware features:
4747
+===========+============+======================+
4848
| UART | on-chip | serial port |
4949
+-----------+------------+----------------------+
50+
| GPIO | on-chip | GPIO driver |
51+
+-----------+------------+----------------------+

boards/arm/raspberrypi_pico/raspberrypi_pico.dts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515
zephyr,flash = &flash0;
1616
zephyr,console = &uart0;
1717
};
18+
19+
leds {
20+
compatible = "gpio-leds";
21+
led0: led_0 {
22+
gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
23+
label = "LED";
24+
};
25+
};
26+
27+
aliases {
28+
led0 = &led0;
29+
};
1830
};
1931

2032
&flash0 {
@@ -30,3 +42,7 @@
3042
pinctrl-0 = <&uart0_default>;
3143
pinctrl-names = "default";
3244
};
45+
46+
&gpio0 {
47+
status = "okay";
48+
};

boards/arm/raspberrypi_pico/raspberrypi_pico.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ toolchain:
1010
- xtools
1111
supported:
1212
- serial
13+
- gpio

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SAM4L gpio_sam4l.c)
2828
zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c)
2929
zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c)
3030
zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c)
31+
zephyr_library_sources_ifdef(CONFIG_GPIO_RPI_PICO gpio_rpi_pico.c)
3132
zephyr_library_sources_ifdef(CONFIG_GPIO_RV32M1 gpio_rv32m1.c)
3233
zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c)
3334
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright (c) 2021 Yonatan Schachter
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config GPIO_RPI_PICO
5+
bool "Raspberry Pi Pico GPIO driver"

drivers/gpio/gpio_rpi_pico.c

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

dts/arm/raspberrypi/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
/ {
@@ -54,6 +55,16 @@
5455
label = "PINCTRL";
5556
};
5657

58+
gpio0: gpio@40014000 {
59+
compatible = "raspberrypi,pico-gpio";
60+
reg = <0x40014000 DT_SIZE_K(4)>;
61+
interrupts = <13 3>;
62+
gpio-controller;
63+
#gpio-cells = <2>;
64+
label = "GPIO_0";
65+
status = "disabled";
66+
};
67+
5768
uart0: uart@40034000 {
5869
compatible = "raspberrypi,pico-uart";
5970
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

0 commit comments

Comments
 (0)