-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
gpio_ene_kb1200.c
210 lines (183 loc) · 7.19 KB
/
gpio_ene_kb1200.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
* Copyright (c) 2023 ENE Technology Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT ene_kb1200_gpio
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/sys/util_macro.h>
#include <reg/gpio.h>
#include <reg/gptd.h>
struct gpio_kb1200_data {
/* gpio_driver_data needs to be first */
struct gpio_driver_data common;
sys_slist_t cb;
};
struct gpio_kb1200_config {
/* gpio_driver_config needs to be first */
struct gpio_driver_config common;
/* base address of GPIO port */
struct gpio_regs *gpio_regs;
struct gptd_regs *gptd_regs;
};
static void gpio_kb1200_isr(const struct device *dev)
{
const struct gpio_kb1200_config *config = dev->config;
struct gpio_kb1200_data *context = dev->data;
uint32_t pending_flag = config->gptd_regs->GPTDPF;
gpio_fire_callbacks(&context->cb, dev, pending_flag);
config->gptd_regs->GPTDPF |= pending_flag;
}
static int kb1200_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
{
const struct gpio_kb1200_config *config = dev->config;
WRITE_BIT(config->gpio_regs->GPIOFS, pin, 0);
if ((flags & GPIO_OUTPUT) != 0) {
WRITE_BIT(config->gpio_regs->GPIOIE, pin, 1);
if ((flags & GPIO_SINGLE_ENDED) != 0) {
if (flags & GPIO_LINE_OPEN_DRAIN) {
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 1);
}
} else {
WRITE_BIT(config->gpio_regs->GPIOOD, pin, 0);
}
if (flags & GPIO_PULL_UP) {
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 1);
} else {
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 0);
}
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
WRITE_BIT(config->gpio_regs->GPIOD, pin, 1);
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
WRITE_BIT(config->gpio_regs->GPIOD, pin, 0);
}
WRITE_BIT(config->gpio_regs->GPIOOE, pin, 1);
} else {
WRITE_BIT(config->gpio_regs->GPIOOE, pin, 0);
if (flags & GPIO_PULL_UP) {
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 1);
} else {
WRITE_BIT(config->gpio_regs->GPIOPU, pin, 0);
}
WRITE_BIT(config->gpio_regs->GPIOIE, pin, 1);
}
return 0;
}
static int kb1200_gpio_port_get_raw(const struct device *dev, gpio_port_value_t *value)
{
const struct gpio_kb1200_config *config = dev->config;
*value = config->gpio_regs->GPIOIN;
return 0;
}
static int kb1200_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
gpio_port_value_t value)
{
const struct gpio_kb1200_config *config = dev->config;
config->gpio_regs->GPIOD |= (value & mask);
return 0;
}
static int kb1200_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
{
const struct gpio_kb1200_config *config = dev->config;
config->gpio_regs->GPIOD |= pins;
return 0;
}
static int kb1200_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
{
const struct gpio_kb1200_config *config = dev->config;
config->gpio_regs->GPIOD &= ~pins;
return 0;
}
static int kb1200_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
{
const struct gpio_kb1200_config *config = dev->config;
config->gpio_regs->GPIOD ^= pins;
return 0;
}
static int kb1200_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
enum gpio_int_mode mode, enum gpio_int_trig trig)
{
const struct gpio_kb1200_config *config = dev->config;
/* Check if GPIO port needs interrupt support */
if ((mode & GPIO_INT_DISABLE) || (mode & GPIO_INT_ENABLE) == 0) {
/* Set the mask to disable the interrupt */
WRITE_BIT(config->gptd_regs->GPTDIE, pin, 0);
} else {
if (mode & GPIO_INT_EDGE) {
WRITE_BIT(config->gptd_regs->GPTDEL, pin, 0);
if (trig & GPIO_INT_HIGH_1) {
if (trig & GPIO_INT_LOW_0) { /* Falling & Rising edge trigger */
/* Enable toggle trigger */
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 1);
} else { /* Rising edge */
/* Disable toggle trigger */
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 1);
}
} else { /* Falling edge */
/* Disable Toggle trigger */
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 0);
}
} else {
WRITE_BIT(config->gptd_regs->GPTDEL, pin, 1);
/* Disable Toggle trigger */
WRITE_BIT(config->gptd_regs->GPTDCHG, pin, 0);
if (trig & GPIO_INT_HIGH_1) {
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 1);
} else {
WRITE_BIT(config->gptd_regs->GPTDPS, pin, 0);
}
}
/* clear pending flag */
WRITE_BIT(config->gptd_regs->GPTDPF, pin, 1);
/* Enable the interrupt */
WRITE_BIT(config->gptd_regs->GPTDIE, pin, 1);
}
return 0;
}
static int kb1200_gpio_manage_callback(const struct device *dev, struct gpio_callback *cb, bool set)
{
struct gpio_kb1200_data *context = dev->data;
gpio_manage_callback(&context->cb, cb, set);
return 0;
}
static uint32_t kb1200_gpio_get_pending_int(const struct device *dev)
{
const struct gpio_kb1200_config *const config = dev->config;
return config->gptd_regs->GPTDPF;
}
static const struct gpio_driver_api kb1200_gpio_api = {
.pin_configure = kb1200_gpio_pin_configure,
.port_get_raw = kb1200_gpio_port_get_raw,
.port_set_masked_raw = kb1200_gpio_port_set_masked_raw,
.port_set_bits_raw = kb1200_gpio_port_set_bits_raw,
.port_clear_bits_raw = kb1200_gpio_port_clear_bits_raw,
.port_toggle_bits = kb1200_gpio_port_toggle_bits,
.pin_interrupt_configure = kb1200_gpio_pin_interrupt_configure,
.manage_callback = kb1200_gpio_manage_callback,
.get_pending_int = kb1200_gpio_get_pending_int,
};
#define KB1200_GPIO_INIT(n) \
static int kb1200_gpio_##n##_init(const struct device *dev) \
{ \
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq), DT_INST_IRQ_BY_IDX(n, 0, priority), \
gpio_kb1200_isr, DEVICE_DT_INST_GET(n), 0); \
irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq)); \
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 1, irq), DT_INST_IRQ_BY_IDX(n, 1, priority), \
gpio_kb1200_isr, DEVICE_DT_INST_GET(n), 0); \
irq_enable(DT_INST_IRQ_BY_IDX(n, 1, irq)); \
return 0; \
}; \
static const struct gpio_kb1200_config port_##n##_kb1200_config = { \
.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n)}, \
.gpio_regs = (struct gpio_regs *)DT_INST_REG_ADDR_BY_IDX(n, 0), \
.gptd_regs = (struct gptd_regs *)DT_INST_REG_ADDR_BY_IDX(n, 1), \
}; \
static struct gpio_kb1200_data gpio_kb1200_##n##_data; \
DEVICE_DT_INST_DEFINE(n, &kb1200_gpio_##n##_init, NULL, &gpio_kb1200_##n##_data, \
&port_##n##_kb1200_config, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &kb1200_gpio_api);
DT_INST_FOREACH_STATUS_OKAY(KB1200_GPIO_INIT)