1 /*
2 * Copyright (c) 2021 Andes Technology Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file GPIO driver for the AndesTech ATCGPIO100 controller
9 */
10
11 #include <errno.h>
12 #include <stdbool.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/dt-bindings/gpio/andestech-atcgpio100.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/sys/sys_io.h>
19 #include <zephyr/irq.h>
20
21 #include <zephyr/drivers/gpio/gpio_utils.h>
22
23 #define DT_DRV_COMPAT andestech_atcgpio100
24
25 /* Andes ATCGPIO100 register definition */
26 #define REG_IDR 0x00 /* ID and Revision reg. */
27 #define REG_CFG 0x10 /* Hardware configure reg. */
28 #define REG_DIN 0x20 /* Data In reg. */
29 #define REG_DOUT 0x24 /* Data Out reg. */
30 #define REG_DIR 0x28 /* Channel direction reg. */
31 #define REG_DCLR 0x2C /* Data out clear reg. */
32 #define REG_DSET 0x30 /* Data out set reg. */
33 #define REG_PUEN 0x40 /* Pull enable reg. */
34 #define REG_PTYP 0x44 /* Pull type reg. */
35 #define REG_INTE 0x50 /* Interrupt enable reg. */
36 #define REG_IMD0 0x54 /* Interrupt mode 0 ~ 7 reg. */
37 #define REG_IMD1 0x58 /* Interrupt mode 8 ~ 15 reg. */
38 #define REG_IMD2 0x5C /* Interrupt mode 16 ~ 23 reg. */
39 #define REG_IMD3 0x60 /* Interrupt mode 24 ~ 31 reg. */
40 #define REG_ISTA 0x64 /* Interrupt status reg. */
41 #define REG_DEBE 0x70 /* De-bounce enable reg. */
42 #define REG_DEBC 0x74 /* De-Bounce control reg. */
43
44 #define INT_NO_OPERATION 0x0
45 #define INT_HIGH_LEVEL 0x2
46 #define INT_LOW_LEVEL 0x3
47 #define INT_NEGATIVE_EDGE 0x5
48 #define INT_POSITIVE_EDGE 0x6
49 #define INT_DUAL_EDGE 0x7
50
51 #define PULL_CONFIGURED BIT(31)
52 #define DEBOUNCE_CONFIGURED BIT(29)
53 #define DF_DEBOUNCED_SETTING (0x80000003)
54
55 #define GPIO_BASE(dev) \
56 ((const struct gpio_atcgpio100_config * const)(dev)->config)->base
57
58 #define GPIO_CFG(dev) (GPIO_BASE(dev) + REG_CFG)
59 #define GPIO_DIR(dev) (GPIO_BASE(dev) + REG_DIR)
60 #define GPIO_DIN(dev) (GPIO_BASE(dev) + REG_DIN)
61 #define GPIO_DOUT(dev) (GPIO_BASE(dev) + REG_DOUT)
62 #define GPIO_DCLR(dev) (GPIO_BASE(dev) + REG_DCLR)
63 #define GPIO_DSET(dev) (GPIO_BASE(dev) + REG_DSET)
64 #define GPIO_PUEN(dev) (GPIO_BASE(dev) + REG_PUEN)
65 #define GPIO_PTYP(dev) (GPIO_BASE(dev) + REG_PTYP)
66 #define GPIO_INTE(dev) (GPIO_BASE(dev) + REG_INTE)
67 #define GPIO_IMD(dev, idx) (GPIO_BASE(dev) + REG_IMD0 + (idx * 4))
68 #define GPIO_ISTA(dev) (GPIO_BASE(dev) + REG_ISTA)
69 #define GPIO_DEBE(dev) (GPIO_BASE(dev) + REG_DEBE)
70 #define GPIO_DEBC(dev) (GPIO_BASE(dev) + REG_DEBC)
71
72 #define SET_GPIO_INT_MODE(cur_val, mode, ch_idx) \
73 do { \
74 cur_val &= ~(BIT_MASK(3) << (ch_idx * 4)); \
75 cur_val |= (mode << (ch_idx * 4)); \
76 } while (false)
77
78
79 typedef void (*atcgpio100_cfg_func_t)(void);
80
81 struct gpio_atcgpio100_config {
82 /* gpio_driver_config needs to be first */
83 struct gpio_driver_config common;
84 uint32_t base;
85 uint32_t irq_num;
86 atcgpio100_cfg_func_t cfg_func;
87 };
88
89 struct gpio_atcgpio100_data {
90 /* gpio_driver_data needs to be first */
91 struct gpio_driver_data common;
92 /* list of callbacks */
93 sys_slist_t cb;
94 struct k_spinlock lock;
95 };
96
gpio_atcgpio100_config(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)97 static int gpio_atcgpio100_config(const struct device *port,
98 gpio_pin_t pin,
99 gpio_flags_t flags)
100 {
101 struct gpio_atcgpio100_data * const data = port->data;
102 uint32_t port_value, pin_mask, io_flags;
103 k_spinlock_key_t key;
104
105 /* Does not support disconnected pin, and
106 * not supporting both input/output at same time.
107 */
108 io_flags = flags & (GPIO_INPUT | GPIO_OUTPUT);
109 if ((io_flags == GPIO_DISCONNECTED)
110 || (io_flags == (GPIO_INPUT | GPIO_OUTPUT))) {
111 return -ENOTSUP;
112 }
113
114 pin_mask = BIT(pin);
115
116 if (flags & GPIO_OUTPUT) {
117
118 if (flags & GPIO_OUTPUT_INIT_HIGH) {
119 sys_write32(pin_mask, GPIO_DSET(port));
120 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
121 sys_write32(pin_mask, GPIO_DCLR(port));
122 }
123
124 key = k_spin_lock(&data->lock);
125
126 /* Set channel output */
127 port_value = sys_read32(GPIO_DIR(port));
128 sys_write32((port_value | pin_mask), GPIO_DIR(port));
129
130 k_spin_unlock(&data->lock, key);
131
132 } else if (flags & GPIO_INPUT) {
133
134 if (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) {
135 return -ENOTSUP;
136 }
137
138 key = k_spin_lock(&data->lock);
139
140 /* Set de-bounce */
141 if (flags & ATCGPIO100_GPIO_DEBOUNCE) {
142 /* Default settings: Filter out pulses which are
143 * less than 4 de-bounce clock period
144 */
145 sys_write32(DF_DEBOUNCED_SETTING, GPIO_DEBC(port));
146 port_value = sys_read32(GPIO_DEBE(port));
147 sys_write32((port_value | pin_mask), GPIO_DEBE(port));
148 }
149
150 /* Set channel input */
151 port_value = sys_read32(GPIO_DIR(port));
152 sys_write32((port_value & ~pin_mask), GPIO_DIR(port));
153
154 k_spin_unlock(&data->lock, key);
155
156 } else {
157 return -ENOTSUP;
158 }
159
160 return 0;
161 }
162
gpio_atcgpio100_port_get_raw(const struct device * port,gpio_port_value_t * value)163 static int gpio_atcgpio100_port_get_raw(const struct device *port,
164 gpio_port_value_t *value)
165 {
166 *value = sys_read32(GPIO_DIN(port));
167 return 0;
168 }
169
gpio_atcgpio100_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)170 static int gpio_atcgpio100_set_masked_raw(const struct device *port,
171 gpio_port_pins_t mask,
172 gpio_port_value_t value)
173 {
174 struct gpio_atcgpio100_data * const data = port->data;
175 uint32_t port_value;
176
177 k_spinlock_key_t key = k_spin_lock(&data->lock);
178
179 port_value = sys_read32(GPIO_DOUT(port));
180 sys_write32((port_value & ~mask) | (value & mask), GPIO_DOUT(port));
181
182 k_spin_unlock(&data->lock, key);
183
184 return 0;
185 }
186
gpio_atcgpio100_set_bits_raw(const struct device * port,gpio_port_pins_t pins)187 static int gpio_atcgpio100_set_bits_raw(const struct device *port,
188 gpio_port_pins_t pins)
189 {
190 sys_write32(pins, GPIO_DSET(port));
191 return 0;
192 }
193
gpio_atcgpio100_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)194 static int gpio_atcgpio100_clear_bits_raw(const struct device *port,
195 gpio_port_pins_t pins)
196 {
197 sys_write32(pins, GPIO_DCLR(port));
198 return 0;
199 }
200
gpio_atcgpio100_toggle_bits(const struct device * port,gpio_port_pins_t pins)201 static int gpio_atcgpio100_toggle_bits(const struct device *port,
202 gpio_port_pins_t pins)
203 {
204 struct gpio_atcgpio100_data * const data = port->data;
205 uint32_t port_value;
206
207 k_spinlock_key_t key = k_spin_lock(&data->lock);
208
209 port_value = sys_read32(GPIO_DOUT(port));
210 sys_write32((port_value ^ pins), GPIO_DOUT(port));
211
212 k_spin_unlock(&data->lock, key);
213
214 return 0;
215 }
216
gpio_atcgpio100_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)217 static int gpio_atcgpio100_pin_interrupt_configure(
218 const struct device *port,
219 gpio_pin_t pin,
220 enum gpio_int_mode mode,
221 enum gpio_int_trig trig)
222 {
223 struct gpio_atcgpio100_data * const data = port->data;
224 uint32_t port_value, int_mode, imr_idx, ch_idx;
225 k_spinlock_key_t key;
226
227 switch (mode | trig) {
228 case GPIO_INT_EDGE_BOTH:
229 int_mode = INT_DUAL_EDGE;
230 break;
231 case GPIO_INT_EDGE_RISING:
232 int_mode = INT_POSITIVE_EDGE;
233 break;
234 case GPIO_INT_EDGE_FALLING:
235 int_mode = INT_NEGATIVE_EDGE;
236 break;
237 case GPIO_INT_LEVEL_LOW:
238 int_mode = INT_LOW_LEVEL;
239 break;
240 case GPIO_INT_LEVEL_HIGH:
241 int_mode = INT_HIGH_LEVEL;
242 break;
243 default:
244 int_mode = INT_NO_OPERATION;
245 break;
246 }
247
248 imr_idx = (pin / 8);
249 ch_idx = (pin % 8);
250
251 key = k_spin_lock(&data->lock);
252
253 if (int_mode == INT_NO_OPERATION) {
254 /* Disable interrupt of pin */
255 port_value = sys_read32(GPIO_INTE(port));
256 sys_write32((port_value & ~BIT(pin)), GPIO_INTE(port));
257
258 /* Clear the remain pending interrupt */
259 port_value = sys_read32(GPIO_ISTA(port));
260 sys_write32(port_value, GPIO_ISTA(port));
261 } else {
262 /* Set interrupt mode of pin */
263 port_value = sys_read32(GPIO_IMD(port, imr_idx));
264 SET_GPIO_INT_MODE(port_value, int_mode, ch_idx);
265 sys_write32(port_value, GPIO_IMD(port, imr_idx));
266
267 /* Enable interrupt of pin */
268 port_value = sys_read32(GPIO_INTE(port));
269 sys_write32((port_value | BIT(pin)), GPIO_INTE(port));
270 }
271
272 k_spin_unlock(&data->lock, key);
273
274 return 0;
275 }
276
gpio_atcgpio100_manage_callback(const struct device * port,struct gpio_callback * callback,bool set)277 static int gpio_atcgpio100_manage_callback(const struct device *port,
278 struct gpio_callback *callback,
279 bool set)
280 {
281
282 struct gpio_atcgpio100_data * const data = port->data;
283
284 return gpio_manage_callback(&data->cb, callback, set);
285 }
286
287 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_atcgpio100_port_get_dir(const struct device * port,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)288 static int gpio_atcgpio100_port_get_dir(const struct device *port,
289 gpio_port_pins_t map,
290 gpio_port_pins_t *inputs,
291 gpio_port_pins_t *outputs)
292 {
293 const struct gpio_atcgpio100_config * const dev_cfg = port->config;
294 uint32_t direction = sys_read32(GPIO_DIR(port));
295
296 map &= dev_cfg->common.port_pin_mask;
297
298 if (inputs != NULL) {
299 *inputs = map & ~direction;
300 }
301
302 if (outputs != NULL) {
303 *outputs = map & direction;
304 }
305
306 return 0;
307 }
308 #endif /* CONFIG_GPIO_GET_DIRECTION */
309
gpio_atcgpio100_irq_handler(const struct device * port)310 static void gpio_atcgpio100_irq_handler(const struct device *port)
311 {
312 struct gpio_atcgpio100_data * const data = port->data;
313 uint32_t port_value;
314
315 port_value = sys_read32(GPIO_ISTA(port));
316 sys_write32(port_value, GPIO_ISTA(port));
317
318 gpio_fire_callbacks(&data->cb, port, port_value);
319
320 }
321
322 static const struct gpio_driver_api gpio_atcgpio100_api = {
323 .pin_configure = gpio_atcgpio100_config,
324 .port_get_raw = gpio_atcgpio100_port_get_raw,
325 .port_set_masked_raw = gpio_atcgpio100_set_masked_raw,
326 .port_set_bits_raw = gpio_atcgpio100_set_bits_raw,
327 .port_clear_bits_raw = gpio_atcgpio100_clear_bits_raw,
328 .port_toggle_bits = gpio_atcgpio100_toggle_bits,
329 .pin_interrupt_configure = gpio_atcgpio100_pin_interrupt_configure,
330 .manage_callback = gpio_atcgpio100_manage_callback,
331 #ifdef CONFIG_GPIO_GET_DIRECTION
332 .port_get_direction = gpio_atcgpio100_port_get_dir,
333 #endif /* CONFIG_GPIO_GET_DIRECTION */
334 };
335
gpio_atcgpio100_init(const struct device * port)336 static int gpio_atcgpio100_init(const struct device *port)
337 {
338 const struct gpio_atcgpio100_config * const dev_cfg = port->config;
339
340 /* Disable all interrupts */
341 sys_write32(BIT_MASK(0), GPIO_INTE(port));
342
343 /* Write 1 to clear interrupt status */
344 sys_write32((uint32_t) BIT64_MASK(32), GPIO_ISTA(port));
345
346 /* Configure GPIO device */
347 dev_cfg->cfg_func();
348
349 /* Enable PLIC interrupt GPIO source */
350 irq_enable(dev_cfg->irq_num);
351
352 return 0;
353 }
354
355 #define GPIO_ATCGPIO100_INIT(n) \
356 static void gpio_atcgpio100_cfg_func_##n(void); \
357 static struct gpio_atcgpio100_data gpio_atcgpio100_data_##n; \
358 \
359 static const struct gpio_atcgpio100_config \
360 gpio_atcgpio100_config_##n = { \
361 .common = { \
362 .port_pin_mask = \
363 GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
364 }, \
365 .base = DT_INST_REG_ADDR(n), \
366 .irq_num = DT_INST_IRQN(n), \
367 .cfg_func = gpio_atcgpio100_cfg_func_##n \
368 }; \
369 \
370 DEVICE_DT_INST_DEFINE(n, \
371 gpio_atcgpio100_init, \
372 NULL, \
373 &gpio_atcgpio100_data_##n, \
374 &gpio_atcgpio100_config_##n, \
375 PRE_KERNEL_1, \
376 CONFIG_GPIO_INIT_PRIORITY, \
377 &gpio_atcgpio100_api); \
378 \
379 static void gpio_atcgpio100_cfg_func_##n(void) \
380 { \
381 IRQ_CONNECT(DT_INST_IRQN(n), \
382 DT_INST_IRQ(n, priority), \
383 gpio_atcgpio100_irq_handler, \
384 DEVICE_DT_INST_GET(n), \
385 0); \
386 return; \
387 } \
388
389
390 DT_INST_FOREACH_STATUS_OKAY(GPIO_ATCGPIO100_INIT)
391