Skip to content

Commit 7d2be3b

Browse files
ene-stevenkartben
authored andcommitted
drivers: gpio: gpio driver
Add gpio driver for ENE KB106X Signed-off-by: Steven Chang <[email protected]>
1 parent d9310b6 commit 7d2be3b

File tree

8 files changed

+467
-0
lines changed

8 files changed

+467
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_DAVINCI gpio_davinci.c)
2525
zephyr_library_sources_ifdef(CONFIG_GPIO_DW gpio_dw.c)
2626
zephyr_library_sources_ifdef(CONFIG_GPIO_EFINIX_SAPPHIRE gpio_efinix_sapphire.c)
2727
zephyr_library_sources_ifdef(CONFIG_GPIO_EMUL gpio_emul.c)
28+
zephyr_library_sources_ifdef(CONFIG_GPIO_ENE_KB106X gpio_ene_kb106x.c)
2829
zephyr_library_sources_ifdef(CONFIG_GPIO_ENE_KB1200 gpio_ene_kb1200.c)
2930
zephyr_library_sources_ifdef(CONFIG_GPIO_EOS_S3 gpio_eos_s3.c)
3031
zephyr_library_sources_ifdef(CONFIG_GPIO_ESP32 gpio_esp32.c)

drivers/gpio/Kconfig.ene

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,10 @@ config GPIO_ENE_KB1200
77
depends on DT_HAS_ENE_KB1200_GPIO_ENABLED
88
help
99
Enable support for the kb1200 GPIO controllers.
10+
11+
config GPIO_ENE_KB106X
12+
bool "ENE KB106X GPIO Driver"
13+
default y
14+
depends on DT_HAS_ENE_KB106X_GPIO_ENABLED
15+
help
16+
Enable support for the KB106X GPIO controllers.

drivers/gpio/gpio_ene_kb106x.c

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
/*
2+
* Copyright (c) 2025 ENE Technology Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ene_kb106x_gpio
8+
9+
#include <zephyr/kernel.h>
10+
#include <zephyr/drivers/gpio.h>
11+
#include <zephyr/drivers/gpio/gpio_utils.h>
12+
#include <zephyr/dt-bindings/gpio/ene-kb106x-gpio.h>
13+
#include <zephyr/sys/util_macro.h>
14+
#include <reg/gpio.h>
15+
#include <reg/gptd.h>
16+
17+
struct gpio_kb106x_data {
18+
/* gpio_driver_data needs to be first */
19+
struct gpio_driver_data common;
20+
sys_slist_t cb;
21+
};
22+
23+
struct gpio_kb106x_config {
24+
/* gpio_driver_config needs to be first */
25+
struct gpio_driver_config common;
26+
/* base address of GPIO port */
27+
struct gpio_regs *gpio_regs;
28+
struct gptd_regs *gptd_regs;
29+
};
30+
31+
static void gpio_kb106x_isr(const struct device *dev)
32+
{
33+
const struct gpio_kb106x_config *config = dev->config;
34+
struct gpio_kb106x_data *context = dev->data;
35+
uint32_t pending_flag = config->gptd_regs->GPTDPF;
36+
37+
gpio_fire_callbacks(&context->cb, dev, pending_flag);
38+
config->gptd_regs->GPTDPF = pending_flag;
39+
}
40+
41+
static int kb106x_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
42+
{
43+
const struct gpio_kb106x_config *config = dev->config;
44+
45+
/* ene specific flags. low voltage mode, input voltage threshold (ViH & ViL) 1.8V */
46+
if (flags & ENE_GPIO_VOLTAGE_1P8) {
47+
WRITE_BIT(config->gpio_regs->GPIOLV, pin, 1);
48+
} else {
49+
WRITE_BIT(config->gpio_regs->GPIOLV, pin, 0);
50+
}
51+
/* ene specific flags. max current driving ability, max support 16 mA */
52+
if (flags & ENE_GPIO_DRIVING_16MA) {
53+
WRITE_BIT(config->gpio_regs->GPIODC, pin, 1);
54+
} else {
55+
WRITE_BIT(config->gpio_regs->GPIODC, pin, 0);
56+
}
57+
/* pull-up function */
58+
if (flags & GPIO_PULL_UP) {
59+
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 1);
60+
} else {
61+
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 0);
62+
}
63+
/* output data high/low */
64+
if (flags & GPIO_OUTPUT_INIT_HIGH) {
65+
WRITE_BIT(config->gpio_regs->GPIOD, pin, 1);
66+
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
67+
WRITE_BIT(config->gpio_regs->GPIOD, pin, 0);
68+
}
69+
/* output enable function */
70+
if (flags & GPIO_OUTPUT) {
71+
/* [patch] setting open-drain only when output is enabled */
72+
/* output type push-pull/open-drain */
73+
if (flags & GPIO_SINGLE_ENDED) {
74+
if (flags & GPIO_LINE_OPEN_DRAIN) {
75+
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 1);
76+
} else {
77+
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 0);
78+
}
79+
} else {
80+
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 0);
81+
}
82+
WRITE_BIT(config->gpio_regs->GPIOOE, pin, 1);
83+
} else {
84+
WRITE_BIT(config->gpio_regs->GPIOOE, pin, 0);
85+
/* [patch] disable open-drain when output is disabled */
86+
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 0);
87+
}
88+
/* input enable function */
89+
if (flags & GPIO_INPUT) {
90+
WRITE_BIT(config->gpio_regs->GPIOIE, pin, 1);
91+
} else {
92+
WRITE_BIT(config->gpio_regs->GPIOIE, pin, 0);
93+
}
94+
95+
return 0;
96+
}
97+
98+
static int kb106x_gpio_port_get_raw(const struct device *dev, gpio_port_value_t *value)
99+
{
100+
const struct gpio_kb106x_config *config = dev->config;
101+
102+
*value = config->gpio_regs->GPIOIN;
103+
return 0;
104+
}
105+
106+
static int kb106x_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
107+
gpio_port_value_t value)
108+
{
109+
const struct gpio_kb106x_config *config = dev->config;
110+
111+
config->gpio_regs->GPIOD |= (value & mask);
112+
return 0;
113+
}
114+
115+
static int kb106x_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
116+
{
117+
const struct gpio_kb106x_config *config = dev->config;
118+
119+
config->gpio_regs->GPIOD |= pins;
120+
return 0;
121+
}
122+
123+
static int kb106x_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
124+
{
125+
const struct gpio_kb106x_config *config = dev->config;
126+
127+
config->gpio_regs->GPIOD &= ~pins;
128+
return 0;
129+
}
130+
131+
static int kb106x_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
132+
{
133+
const struct gpio_kb106x_config *config = dev->config;
134+
135+
config->gpio_regs->GPIOD ^= pins;
136+
return 0;
137+
}
138+
139+
static int kb106x_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
140+
enum gpio_int_mode mode, enum gpio_int_trig trig)
141+
{
142+
const struct gpio_kb106x_config *config = dev->config;
143+
144+
if (mode & GPIO_INT_EDGE) {
145+
WRITE_BIT(config->gptd_regs->GPTDEL, pin, 0);
146+
if (trig & GPIO_INT_HIGH_1) {
147+
if (trig & GPIO_INT_LOW_0) { /* Falling & Rising edge trigger */
148+
/* Enable toggle trigger */
149+
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 1);
150+
} else { /* Rising edge */
151+
/* Disable toggle trigger */
152+
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
153+
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 1);
154+
}
155+
} else { /* Falling edge */
156+
/* Disable Toggle trigger */
157+
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
158+
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 0);
159+
}
160+
} else {
161+
WRITE_BIT(config->gptd_regs->GPTDEL, pin, 1);
162+
/* Disable Toggle trigger */
163+
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
164+
if (trig & GPIO_INT_HIGH_1) {
165+
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 1);
166+
} else {
167+
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 0);
168+
}
169+
}
170+
171+
/* clear pending flag */
172+
WRITE_BIT(config->gptd_regs->GPTDPF, pin, 1);
173+
174+
/* Check if GPIO port needs interrupt support */
175+
if ((mode & GPIO_INT_DISABLE) || (mode & GPIO_INT_ENABLE) == 0) {
176+
/* Set the mask to disable the interrupt */
177+
WRITE_BIT(config->gptd_regs->GPTDIE, pin, 0);
178+
} else {
179+
/* Enable the interrupt */
180+
WRITE_BIT(config->gptd_regs->GPTDIE, pin, 1);
181+
}
182+
183+
/* Check GPIO wakeup enable */
184+
if (trig & GPIO_INT_TRIG_WAKE) {
185+
WRITE_BIT(config->gptd_regs->GPTDWE, pin, 1);
186+
} else {
187+
WRITE_BIT(config->gptd_regs->GPTDWE, pin, 0);
188+
}
189+
return 0;
190+
}
191+
192+
static int kb106x_gpio_manage_callback(const struct device *dev, struct gpio_callback *cb, bool set)
193+
{
194+
struct gpio_kb106x_data *context = dev->data;
195+
196+
gpio_manage_callback(&context->cb, cb, set);
197+
return 0;
198+
}
199+
200+
static uint32_t kb106x_gpio_get_pending_int(const struct device *dev)
201+
{
202+
const struct gpio_kb106x_config *const config = dev->config;
203+
204+
return config->gptd_regs->GPTDPF;
205+
}
206+
207+
static const struct gpio_driver_api kb106x_gpio_api = {
208+
.pin_configure = kb106x_gpio_pin_configure,
209+
.port_get_raw = kb106x_gpio_port_get_raw,
210+
.port_set_masked_raw = kb106x_gpio_port_set_masked_raw,
211+
.port_set_bits_raw = kb106x_gpio_port_set_bits_raw,
212+
.port_clear_bits_raw = kb106x_gpio_port_clear_bits_raw,
213+
.port_toggle_bits = kb106x_gpio_port_toggle_bits,
214+
.pin_interrupt_configure = kb106x_gpio_pin_interrupt_configure,
215+
.manage_callback = kb106x_gpio_manage_callback,
216+
.get_pending_int = kb106x_gpio_get_pending_int,
217+
};
218+
219+
#define KB106X_GPIO_INIT(n) \
220+
static int kb106x_gpio_##n##_init(const struct device *dev) \
221+
{ \
222+
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq), DT_INST_IRQ_BY_IDX(n, 0, priority), \
223+
gpio_kb106x_isr, DEVICE_DT_INST_GET(n), 0); \
224+
irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq)); \
225+
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 1, irq), DT_INST_IRQ_BY_IDX(n, 1, priority), \
226+
gpio_kb106x_isr, DEVICE_DT_INST_GET(n), 0); \
227+
irq_enable(DT_INST_IRQ_BY_IDX(n, 1, irq)); \
228+
return 0; \
229+
}; \
230+
static const struct gpio_kb106x_config port_##n##_kb106x_config = { \
231+
.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n)}, \
232+
.gpio_regs = (struct gpio_regs *)DT_INST_REG_ADDR_BY_IDX(n, 0), \
233+
.gptd_regs = (struct gptd_regs *)DT_INST_REG_ADDR_BY_IDX(n, 1), \
234+
}; \
235+
static struct gpio_kb106x_data gpio_kb106x_##n##_data; \
236+
DEVICE_DT_INST_DEFINE(n, &kb106x_gpio_##n##_init, NULL, &gpio_kb106x_##n##_data, \
237+
&port_##n##_kb106x_config, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
238+
&kb106x_gpio_api);
239+
240+
DT_INST_FOREACH_STATUS_OKAY(KB106X_GPIO_INIT)

dts/arm/ene/kb106x/kb106x.dtsi

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,56 @@
6060
#size-cells = <1>;
6161
reg = <0x50000000 0x100>;
6262
status = "okay";
63+
64+
gpio0x1x: gpio@50000000 {
65+
compatible = "ene,kb106x-gpio";
66+
reg = <0x50000000 0x04>, <0x50010000 0x04>;
67+
interrupts = <2 3>, <3 3>;
68+
gpio-controller;
69+
#gpio-cells = <2>;
70+
ngpios = <32>;
71+
status = "disabled";
72+
};
73+
74+
gpio2x3x: gpio@50000004 {
75+
compatible = "ene,kb106x-gpio";
76+
reg = <0x50000004 0x04>, <0x50010004 0x04>;
77+
interrupts = <4 3>, <5 3>;
78+
gpio-controller;
79+
#gpio-cells = <2>;
80+
ngpios = <32>;
81+
status = "disabled";
82+
};
83+
84+
gpio4x5x: gpio@50000008 {
85+
compatible = "ene,kb106x-gpio";
86+
reg = <0x50000008 0x04>, <0x50010008 0x04>;
87+
interrupts = <6 3>, <7 3>;
88+
gpio-controller;
89+
#gpio-cells = <2>;
90+
ngpios = <32>;
91+
status = "disabled";
92+
};
93+
94+
gpio6x7x: gpio@5000000c {
95+
compatible = "ene,kb106x-gpio";
96+
reg = <0x5000000C 0x04>, <0x5001000C 0x04>;
97+
interrupts = <8 3>, <9 3>;
98+
gpio-controller;
99+
#gpio-cells = <2>;
100+
ngpios = <32>;
101+
status = "disabled";
102+
};
103+
104+
egpio0x1x: gpio@50000100 {
105+
compatible = "ene,kb106x-gpio";
106+
reg = <0x50000100 0x04>, <0x50010100 0x04>;
107+
interrupts = <2 3>, <3 3>;
108+
gpio-controller;
109+
#gpio-cells = <2>;
110+
ngpios = <32>;
111+
status = "disabled";
112+
};
63113
};
64114
};
65115
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) 2025 ENE Technology Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
ENE KB106X GPIO(General purpose IO) Port node
6+
7+
The GPIO controller provides group control of GPIO functions. Each port
8+
group contains 32 pins. GPIO_00~GPIO_1F belong to the Port0 group,
9+
GPIO_20~GPIO_3F belong to the Port1 group, and so on.
10+
11+
In particular, the 32 pins of the port group do not share the same IRQ
12+
interrupt, but are assigned to two different IRQ interrupts in groups of 16
13+
pins. This means that single port group provide two interrupt source.
14+
ex.Port0 group GPIO_00~GPIO_0F shares IRQ18, and Port0 group
15+
GPIO_10~GPIO_1F shares IRQ19.
16+
17+
compatible: "ene,kb106x-gpio"
18+
19+
include: [gpio-controller.yaml, base.yaml]
20+
21+
properties:
22+
reg:
23+
required: true
24+
25+
interrupts:
26+
required: true
27+
28+
"#gpio-cells":
29+
const: 2
30+
31+
gpio-cells:
32+
- pin
33+
- flags
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2025 ENE Technology Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ENE_KB106X_GPIO_H_
7+
#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ENE_KB106X_GPIO_H_
8+
9+
/**
10+
* @name GPIO pin voltage flags
11+
*
12+
* The voltage flags are a Zephyr specific extension of the standard GPIO flags
13+
* specified by the Linux GPIO binding for use with the ENE KB106x SoCs.
14+
*
15+
* @{
16+
* Note: Bits 15 down to 8 are reserved for SoC specific flags.
17+
*/
18+
19+
/** @cond INTERNAL_HIDDEN */
20+
#define ENE_GPIO_VOLTAGE_POS 8
21+
#define ENE_GPIO_VOLTAGE_MASK (1U << ENE_GPIO_VOLTAGE_POS)
22+
23+
#define ENE_GPIO_DRIVING_POS 9
24+
#define ENE_GPIO_DRIVING_MASK (1U << ENE_GPIO_DRIVING_POS)
25+
/** @endcond */
26+
27+
/** Set pin at the default voltage level (3.3V) */
28+
#define ENE_GPIO_VOLTAGE_DEFAULT (0U << ENE_GPIO_VOLTAGE_POS)
29+
/** Set pin voltage level at 1.8 V */
30+
#define ENE_GPIO_VOLTAGE_1P8 (1U << ENE_GPIO_VOLTAGE_POS)
31+
32+
/** Set pin at the default driving current (4mA) */
33+
#define ENE_GPIO_DRIVING_DEFAULT (0U << ENE_GPIO_DRIVING_POS)
34+
/** Set pin driving current at 16mA */
35+
#define ENE_GPIO_DRIVING_16MA (1U << ENE_GPIO_DRIVING_POS)
36+
37+
/** @} */
38+
39+
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ENE_KB106X_GPIO_H_ */

0 commit comments

Comments
 (0)