Skip to content

Commit 38c6962

Browse files
committed
drivers: gpio: add amebadplus gpio driver
GPIO driver for amebadplus Signed-off-by: zjian zhang <zjian_zhang@realsil.com.cn>
1 parent 296fb5b commit 38c6962

File tree

5 files changed

+334
-0
lines changed

5 files changed

+334
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_ADP5585 gpio_adp5585.c)
1010
zephyr_library_sources_ifdef(CONFIG_GPIO_ADS1X4S0X gpio_ads1x4s0x.c)
1111
zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c)
1212
zephyr_library_sources_ifdef(CONFIG_GPIO_AMBIQ gpio_ambiq.c)
13+
zephyr_library_sources_ifdef(CONFIG_GPIO_AMEBA gpio_ameba.c)
1314
zephyr_library_sources_ifdef(CONFIG_GPIO_ANDES_ATCGPIO100 gpio_andes_atcgpio100.c)
1415
zephyr_library_sources_ifdef(CONFIG_GPIO_AW9523B gpio_aw9523b.c)
1516
zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c)

drivers/gpio/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,6 @@ source "drivers/gpio/Kconfig.xlnx_ps"
201201
source "drivers/gpio/Kconfig.xmc4xxx"
202202
# zephyr-keep-sorted-stop
203203

204+
source "drivers/gpio/Kconfig.ameba"
205+
204206
endif # GPIO

drivers/gpio/Kconfig.ameba

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2024 Realtek Semiconductor Corp.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config GPIO_AMEBA
5+
bool "GPIO controller driver for Realtek Ameba series SoC"
6+
default y
7+
depends on DT_HAS_REALTEK_AMEBA_GPIO_ENABLED
8+
help
9+
Enable GPIO controller driver for Realtek Ameba series SoC
10+
11+
config GPIO_DEBOUNCE_EN
12+
bool "Ameba GPIO Interrupt Debounce Enable"
13+
depends on GPIO_AMEBA
14+
default y
15+
help
16+
When Enable GPIO Interrupt Debounce, the external signal can be debounced to
17+
remove any spurious glitches that are less than one period(about 32us) of
18+
the external debouncing clock.

drivers/gpio/gpio_ameba.c

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/*
2+
* Copyright (c) 2024 Realtek Semiconductor Corp.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT realtek_ameba_gpio
8+
9+
/* Include <soc.h> before <ameba_soc.h> to avoid redefining unlikely() macro */
10+
#include <soc.h>
11+
#include <ameba_soc.h>
12+
13+
#include <zephyr/drivers/gpio.h>
14+
#include <zephyr/drivers/gpio/gpio_utils.h>
15+
#include <zephyr/irq.h>
16+
17+
#include <zephyr/logging/log.h>
18+
LOG_MODULE_REGISTER(gpio_ameba, CONFIG_GPIO_LOG_LEVEL);
19+
20+
#define GPIO_PINNAME(PORT, PIN) (((PORT) << 5) | ((PIN) & 0x1F))
21+
22+
struct gpio_ameba_config {
23+
/* gpio_driver_config needs to be first */
24+
struct gpio_driver_config common;
25+
/* port base address */
26+
uint32_t base;
27+
/* IO port */
28+
int port;
29+
};
30+
31+
struct gpio_ameba_data {
32+
/* gpio_driver_data needs to be first */
33+
struct gpio_driver_data common;
34+
/* port ISR callback routine address */
35+
sys_slist_t callbacks;
36+
};
37+
38+
static int gpio_ameba_port_get_raw(const struct device *dev, uint32_t *value)
39+
{
40+
const struct gpio_ameba_config *cfg = dev->config;
41+
42+
*value = GPIO_PortRead(cfg->port, cfg->common.port_pin_mask);
43+
44+
return 0;
45+
}
46+
47+
static int gpio_ameba_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value)
48+
{
49+
const struct gpio_ameba_config *cfg = dev->config;
50+
51+
GPIO_PortDirection(cfg->port, mask, GPIO_Mode_OUT);
52+
GPIO_PortWrite(cfg->port, mask, value);
53+
54+
return 0;
55+
}
56+
57+
static int gpio_ameba_port_set_bits_raw(const struct device *dev, uint32_t mask)
58+
{
59+
const struct gpio_ameba_config *cfg = dev->config;
60+
61+
GPIO_PortWrite(cfg->port, mask, cfg->common.port_pin_mask);
62+
63+
return 0;
64+
}
65+
66+
static int gpio_ameba_port_clear_bits_raw(const struct device *dev, uint32_t mask)
67+
{
68+
const struct gpio_ameba_config *cfg = dev->config;
69+
70+
GPIO_PortWrite(cfg->port, mask, 0);
71+
72+
return 0;
73+
}
74+
75+
static int gpio_ameba_port_toggle_bits(const struct device *dev, uint32_t mask)
76+
{
77+
const struct gpio_ameba_config *cfg = dev->config;
78+
u32 gpio_pin;
79+
u32 value;
80+
uint8_t i;
81+
82+
for (i = 0; i < 32; i++) {
83+
if (mask & 0x1) {
84+
gpio_pin = GPIO_PINNAME(cfg->port, i);
85+
value = GPIO_ReadDataBit(gpio_pin);
86+
GPIO_WriteBit(gpio_pin, (~value) & 0x1);
87+
}
88+
mask >>= 1;
89+
if (mask == 0) {
90+
break;
91+
}
92+
}
93+
94+
return 0;
95+
}
96+
97+
static int gpio_ameba_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
98+
{
99+
const struct gpio_ameba_config *cfg = dev->config;
100+
101+
GPIO_InitTypeDef gpio_initstruct;
102+
u32 gpio_pin;
103+
104+
if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
105+
return -ENOTSUP;
106+
}
107+
108+
if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == 0) {
109+
return -ENOTSUP;
110+
}
111+
112+
gpio_pin = GPIO_PINNAME(cfg->port, pin);
113+
gpio_initstruct.GPIO_Pin = gpio_pin;
114+
115+
if (flags & GPIO_INPUT) {
116+
gpio_initstruct.GPIO_Mode = GPIO_Mode_IN;
117+
} else {
118+
gpio_initstruct.GPIO_Mode = GPIO_Mode_OUT;
119+
}
120+
121+
if (flags & GPIO_PULL_UP) {
122+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_UP;
123+
} else if (flags & GPIO_PULL_DOWN) {
124+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_DOWN;
125+
} else {
126+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
127+
}
128+
129+
GPIO_Init(&gpio_initstruct);
130+
131+
if (flags & GPIO_OUTPUT) {
132+
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
133+
gpio_ameba_port_set_bits_raw(dev, BIT(pin));
134+
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
135+
gpio_ameba_port_clear_bits_raw(dev, BIT(pin));
136+
}
137+
}
138+
139+
return 0;
140+
}
141+
142+
static int gpio_ameba_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
143+
enum gpio_int_mode mode, enum gpio_int_trig trig)
144+
{
145+
const struct gpio_ameba_config *cfg = dev->config;
146+
u32 gpio_pin;
147+
148+
gpio_pin = GPIO_PINNAME(cfg->port, pin);
149+
GPIO_InitTypeDef gpio_initstruct;
150+
151+
gpio_initstruct.GPIO_Pin = gpio_pin;
152+
153+
GPIO_INTConfig(gpio_pin, DISABLE);
154+
155+
LOG_DBG("Config GPIO int:%d-%d, mode:%x, flag:0x%x\n", cfg->port, pin, mode, trig);
156+
gpio_initstruct.GPIO_Pin = gpio_pin;
157+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
158+
gpio_initstruct.GPIO_Mode = GPIO_Mode_INT;
159+
gpio_initstruct.GPIO_ITDebounce = GPIO_INT_DEBOUNCE_DISABLE;
160+
161+
if (mode != GPIO_INT_MODE_DISABLED) {
162+
if (mode & GPIO_INT_MODE_EDGE) {
163+
switch (trig) {
164+
case GPIO_INT_TRIG_LOW:
165+
gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_EDGE;
166+
gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_LOW;
167+
break;
168+
case GPIO_INT_TRIG_HIGH:
169+
gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_EDGE;
170+
gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_HIGH;
171+
break;
172+
case GPIO_INT_TRIG_BOTH:
173+
gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_BOTHEDGE;
174+
break;
175+
default:
176+
LOG_ERR("GPIO Edge interrupt type invalid \r\n");
177+
return -ENOTSUP;
178+
}
179+
} else {
180+
gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_LEVEL;
181+
switch (trig) {
182+
case GPIO_INT_TRIG_LOW:
183+
gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_LOW;
184+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_UP;
185+
break;
186+
case GPIO_INT_TRIG_HIGH:
187+
gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_HIGH;
188+
gpio_initstruct.GPIO_PuPd = GPIO_PuPd_DOWN;
189+
break;
190+
default:
191+
LOG_ERR("GPIO level interrupt doesn't support both high and low");
192+
return -ENOTSUP;
193+
}
194+
}
195+
196+
#if defined(CONFIG_GPIO_DEBOUNCE_EN)
197+
gpio_initstruct.GPIO_ITDebounce = GPIO_INT_DEBOUNCE_ENABLE;
198+
/* GPIO_DebounceClock(cfg->port, DEBOUNCE_DIV_CNT); */
199+
GPIO_Init(&gpio_initstruct);
200+
DelayUs(64);
201+
GPIO_INTConfig(gpio_pin, ENABLE);
202+
#else
203+
GPIO_Init(&gpio_initstruct);
204+
GPIO_INTConfig(gpio_pin, ENABLE);
205+
#endif
206+
} else {
207+
GPIO_Direction(gpio_pin, GPIO_Mode_IN);
208+
PAD_PullCtrl(gpio_pin, gpio_initstruct.GPIO_PuPd);
209+
210+
GPIO_INTMode(gpio_pin, DISABLE, 0, 0, 0);
211+
}
212+
213+
return 0;
214+
}
215+
216+
static int gpio_ameba_manage_callback(const struct device *dev, struct gpio_callback *callback,
217+
bool set)
218+
{
219+
struct gpio_ameba_data *data = dev->data;
220+
221+
return gpio_manage_callback(&data->callbacks, callback, set);
222+
}
223+
224+
static uint32_t gpio_ameba_get_pending_int(const struct device *dev)
225+
{
226+
uint32_t irq_status;
227+
const struct gpio_ameba_config *cfg = dev->config;
228+
uint32_t port = cfg->port;
229+
230+
irq_status = GPIO_INTStatusGet(port);
231+
232+
return irq_status;
233+
}
234+
235+
static void gpio_ameba_isr(const struct device *dev)
236+
{
237+
uint32_t int_status;
238+
struct gpio_ameba_data *data = dev->data;
239+
const struct gpio_ameba_config *cfg = dev->config;
240+
uint32_t port = cfg->port;
241+
242+
/* Get the int status */
243+
int_status = GPIO_INTStatusGet(port);
244+
245+
/* Clear pending edge interrupt */
246+
GPIO_INTStatusClearEdge(port);
247+
248+
/* Call the registered callbacks */
249+
gpio_fire_callbacks(&data->callbacks, dev, int_status);
250+
}
251+
252+
static const struct gpio_driver_api gpio_ameba_driver_api = {
253+
.pin_configure = gpio_ameba_configure,
254+
.port_get_raw = gpio_ameba_port_get_raw,
255+
.port_set_masked_raw = gpio_ameba_port_set_masked_raw,
256+
.port_set_bits_raw = gpio_ameba_port_set_bits_raw,
257+
.port_clear_bits_raw = gpio_ameba_port_clear_bits_raw,
258+
.port_toggle_bits = gpio_ameba_port_toggle_bits,
259+
.pin_interrupt_configure = gpio_ameba_pin_interrupt_configure,
260+
.manage_callback = gpio_ameba_manage_callback,
261+
.get_pending_int = gpio_ameba_get_pending_int,
262+
};
263+
264+
#define GPIO_AMEBA_INIT(n) \
265+
static int gpio_ameba_port##n##_init(const struct device *dev) \
266+
{ \
267+
const struct gpio_ameba_config *cfg = dev->config; \
268+
LOG_INF("GPIO%d INIT, IRQ %d\n", cfg->port, DT_INST_IRQN(n)); \
269+
\
270+
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_ameba_isr, \
271+
DEVICE_DT_INST_GET(n), 0); \
272+
irq_enable(DT_INST_IRQN(n)); \
273+
\
274+
return 0; \
275+
} \
276+
static struct gpio_ameba_data gpio_ameba_port##n##_data; \
277+
\
278+
static const struct gpio_ameba_config gpio_ameba_port##n##_config = { \
279+
.common = \
280+
{ \
281+
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
282+
}, \
283+
.base = DT_INST_REG_ADDR(n), \
284+
.port = n, \
285+
}; \
286+
\
287+
DEVICE_DT_INST_DEFINE(n, gpio_ameba_port##n##_init, NULL, &gpio_ameba_port##n##_data, \
288+
&gpio_ameba_port##n##_config, POST_KERNEL, \
289+
CONFIG_GPIO_INIT_PRIORITY, &gpio_ameba_driver_api);
290+
291+
DT_INST_FOREACH_STATUS_OKAY(GPIO_AMEBA_INIT)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2024 Realtek Semiconductor Corp.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Realtek Ameba GPIO controller
5+
6+
compatible: "realtek,ameba-gpio"
7+
8+
include: [gpio-controller.yaml, base.yaml]
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
interrupts:
15+
required: true
16+
17+
"#gpio-cells":
18+
const: 2
19+
20+
gpio-cells:
21+
- pin
22+
- flags

0 commit comments

Comments
 (0)