1 /*
2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT sifive_gpio0
8
9 /**
10 * @file GPIO driver for the SiFive Freedom Processor
11 */
12
13 #include <errno.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <soc.h>
17 #include <zephyr/drivers/gpio.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/irq.h>
20
21 #include <zephyr/drivers/gpio/gpio_utils.h>
22
23 typedef void (*sifive_cfg_func_t)(void);
24
25 /* sifive GPIO register-set structure */
26 struct gpio_sifive_t {
27 unsigned int in_val;
28 unsigned int in_en;
29 unsigned int out_en;
30 unsigned int out_val;
31 unsigned int pue;
32 unsigned int ds;
33 unsigned int rise_ie;
34 unsigned int rise_ip;
35 unsigned int fall_ie;
36 unsigned int fall_ip;
37 unsigned int high_ie;
38 unsigned int high_ip;
39 unsigned int low_ie;
40 unsigned int low_ip;
41 unsigned int iof_en;
42 unsigned int iof_sel;
43 unsigned int invert;
44 };
45
46 struct gpio_sifive_config {
47 /* gpio_driver_config needs to be first */
48 struct gpio_driver_config common;
49 uintptr_t gpio_base_addr;
50 /* multi-level encoded interrupt corresponding to pin 0 */
51 uint32_t gpio_irq_base;
52 sifive_cfg_func_t gpio_cfg_func;
53 };
54
55 struct gpio_sifive_data {
56 /* gpio_driver_data needs to be first */
57 struct gpio_driver_data common;
58 /* list of callbacks */
59 sys_slist_t cb;
60 };
61
62 /* Helper Macros for GPIO */
63 #define DEV_GPIO_CFG(dev) \
64 ((const struct gpio_sifive_config * const)(dev)->config)
65 #define DEV_GPIO(dev) \
66 ((volatile struct gpio_sifive_t *)(DEV_GPIO_CFG(dev))->gpio_base_addr)
67 #define DEV_GPIO_DATA(dev) \
68 ((struct gpio_sifive_data *)(dev)->data)
69
70
71 /* Given gpio_irq_base and the pin number, return the IRQ number for the pin */
gpio_sifive_pin_irq(unsigned int base_irq,int pin)72 static inline unsigned int gpio_sifive_pin_irq(unsigned int base_irq, int pin)
73 {
74 unsigned int level = irq_get_level(base_irq);
75 unsigned int pin_irq = 0;
76
77 if (level == 1) {
78 pin_irq = base_irq + pin;
79 } else if (level == 2) {
80 pin_irq = base_irq + (pin << CONFIG_1ST_LEVEL_INTERRUPT_BITS);
81 }
82
83 return pin_irq;
84 }
85
86 /* Given the PLIC source number, return the number of the GPIO pin associated
87 * with the interrupt
88 */
gpio_sifive_plic_to_pin(unsigned int base_irq,int plic_irq)89 static inline int gpio_sifive_plic_to_pin(unsigned int base_irq, int plic_irq)
90 {
91 unsigned int level = irq_get_level(base_irq);
92
93 if (level == 2) {
94 base_irq = irq_from_level_2(base_irq);
95 }
96
97 return (plic_irq - base_irq);
98 }
99
gpio_sifive_irq_handler(const struct device * dev)100 static void gpio_sifive_irq_handler(const struct device *dev)
101 {
102 struct gpio_sifive_data *data = DEV_GPIO_DATA(dev);
103 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
104 const struct gpio_sifive_config *cfg = DEV_GPIO_CFG(dev);
105
106 /* Calculate pin and mask from base level 2 line */
107 uint8_t pin = 1 + (riscv_plic_get_irq() -
108 (uint8_t)(cfg->gpio_irq_base >> CONFIG_1ST_LEVEL_INTERRUPT_BITS));
109
110 /* This peripheral tracks each condition separately: a
111 * transition from low to high will mark the pending bit for
112 * both rise and high, while low will probably be set from the
113 * previous state.
114 *
115 * It is certainly possible, especially on double-edge, that
116 * multiple conditions are present. However, there is no way
117 * to tell which one occurred first, and no provision to
118 * indicate which one occurred in the callback.
119 *
120 * Clear all the conditions so we only invoke the callback
121 * once. Level conditions will remain set after clear.
122 */
123 gpio->rise_ip = BIT(pin);
124 gpio->fall_ip = BIT(pin);
125 gpio->high_ip = BIT(pin);
126 gpio->low_ip = BIT(pin);
127
128 /* Call the corresponding callback registered for the pin */
129 gpio_fire_callbacks(&data->cb, dev, BIT(pin));
130 }
131
132 /**
133 * @brief Configure pin
134 *
135 * @param dev Device structure
136 * @param pin The pin number
137 * @param flags Flags of pin or port
138 *
139 * @return 0 if successful, failed otherwise
140 */
gpio_sifive_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)141 static int gpio_sifive_config(const struct device *dev,
142 gpio_pin_t pin,
143 gpio_flags_t flags)
144 {
145 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
146
147 if (pin >= SIFIVE_PINMUX_PINS) {
148 return -EINVAL;
149 }
150
151 /* We cannot support open-source open-drain configuration */
152 if ((flags & GPIO_SINGLE_ENDED) != 0) {
153 return -ENOTSUP;
154 }
155
156 /* We only support pull-ups, not pull-downs */
157 if ((flags & GPIO_PULL_DOWN) != 0) {
158 return -ENOTSUP;
159 }
160
161 /* Set pull-up if requested */
162 WRITE_BIT(gpio->pue, pin, flags & GPIO_PULL_UP);
163
164 /* Set the initial output value before enabling output to avoid
165 * glitches
166 */
167 if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
168 gpio->out_val |= BIT(pin);
169 }
170 if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
171 gpio->out_val &= ~BIT(pin);
172 }
173
174 /* Enable input/output */
175 WRITE_BIT(gpio->out_en, pin, flags & GPIO_OUTPUT);
176 WRITE_BIT(gpio->in_en, pin, flags & GPIO_INPUT);
177
178 return 0;
179 }
180
gpio_sifive_port_get_raw(const struct device * dev,gpio_port_value_t * value)181 static int gpio_sifive_port_get_raw(const struct device *dev,
182 gpio_port_value_t *value)
183 {
184 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
185
186 *value = gpio->in_val;
187
188 return 0;
189 }
190
gpio_sifive_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)191 static int gpio_sifive_port_set_masked_raw(const struct device *dev,
192 gpio_port_pins_t mask,
193 gpio_port_value_t value)
194 {
195 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
196
197 gpio->out_val = (gpio->out_val & ~mask) | (value & mask);
198
199 return 0;
200 }
201
gpio_sifive_port_set_bits_raw(const struct device * dev,gpio_port_pins_t mask)202 static int gpio_sifive_port_set_bits_raw(const struct device *dev,
203 gpio_port_pins_t mask)
204 {
205 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
206
207 gpio->out_val |= mask;
208
209 return 0;
210 }
211
gpio_sifive_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t mask)212 static int gpio_sifive_port_clear_bits_raw(const struct device *dev,
213 gpio_port_pins_t mask)
214 {
215 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
216
217 gpio->out_val &= ~mask;
218
219 return 0;
220 }
221
gpio_sifive_port_toggle_bits(const struct device * dev,gpio_port_pins_t mask)222 static int gpio_sifive_port_toggle_bits(const struct device *dev,
223 gpio_port_pins_t mask)
224 {
225 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
226
227 gpio->out_val ^= mask;
228
229 return 0;
230 }
231
gpio_sifive_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)232 static int gpio_sifive_pin_interrupt_configure(const struct device *dev,
233 gpio_pin_t pin,
234 enum gpio_int_mode mode,
235 enum gpio_int_trig trig)
236 {
237 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
238 const struct gpio_sifive_config *cfg = DEV_GPIO_CFG(dev);
239
240 gpio->rise_ie &= ~BIT(pin);
241 gpio->fall_ie &= ~BIT(pin);
242 gpio->high_ie &= ~BIT(pin);
243 gpio->low_ie &= ~BIT(pin);
244
245 switch (mode) {
246 case GPIO_INT_MODE_DISABLED:
247 irq_disable(gpio_sifive_pin_irq(cfg->gpio_irq_base, pin));
248 break;
249 case GPIO_INT_MODE_LEVEL:
250 /* Board supports both levels, but Zephyr does not. */
251 if (trig == GPIO_INT_TRIG_HIGH) {
252 gpio->high_ip = BIT(pin);
253 gpio->high_ie |= BIT(pin);
254 } else {
255 __ASSERT_NO_MSG(trig == GPIO_INT_TRIG_LOW);
256 gpio->low_ip = BIT(pin);
257 gpio->low_ie |= BIT(pin);
258 }
259 irq_enable(gpio_sifive_pin_irq(cfg->gpio_irq_base, pin));
260 break;
261 case GPIO_INT_MODE_EDGE:
262 __ASSERT_NO_MSG(GPIO_INT_TRIG_BOTH ==
263 (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1));
264
265 if ((trig & GPIO_INT_HIGH_1) != 0) {
266 gpio->rise_ip = BIT(pin);
267 gpio->rise_ie |= BIT(pin);
268 }
269 if ((trig & GPIO_INT_LOW_0) != 0) {
270 gpio->fall_ip = BIT(pin);
271 gpio->fall_ie |= BIT(pin);
272 }
273 irq_enable(gpio_sifive_pin_irq(cfg->gpio_irq_base, pin));
274 break;
275 default:
276 __ASSERT(false, "Invalid MODE %d passed to driver", mode);
277 return -ENOTSUP;
278 }
279
280 return 0;
281 }
282
gpio_sifive_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)283 static int gpio_sifive_manage_callback(const struct device *dev,
284 struct gpio_callback *callback,
285 bool set)
286 {
287 struct gpio_sifive_data *data = DEV_GPIO_DATA(dev);
288
289 return gpio_manage_callback(&data->cb, callback, set);
290 }
291
292 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_sifive_port_get_dir(const struct device * dev,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)293 static int gpio_sifive_port_get_dir(const struct device *dev, gpio_port_pins_t map,
294 gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
295 {
296 const struct gpio_sifive_config *cfg = DEV_GPIO_CFG(dev);
297
298 map &= cfg->common.port_pin_mask;
299
300 if (inputs != NULL) {
301 *inputs = map & DEV_GPIO(dev)->in_en;
302 }
303
304 if (outputs != NULL) {
305 *outputs = map & DEV_GPIO(dev)->out_en;
306 }
307
308 return 0;
309 }
310 #endif /* CONFIG_GPIO_GET_DIRECTION */
311
312 static const struct gpio_driver_api gpio_sifive_driver = {
313 .pin_configure = gpio_sifive_config,
314 .port_get_raw = gpio_sifive_port_get_raw,
315 .port_set_masked_raw = gpio_sifive_port_set_masked_raw,
316 .port_set_bits_raw = gpio_sifive_port_set_bits_raw,
317 .port_clear_bits_raw = gpio_sifive_port_clear_bits_raw,
318 .port_toggle_bits = gpio_sifive_port_toggle_bits,
319 .pin_interrupt_configure = gpio_sifive_pin_interrupt_configure,
320 .manage_callback = gpio_sifive_manage_callback,
321 #ifdef CONFIG_GPIO_GET_DIRECTION
322 .port_get_direction = gpio_sifive_port_get_dir,
323 #endif /* CONFIG_GPIO_GET_DIRECTION */
324 };
325
326 /**
327 * @brief Initialize a GPIO controller
328 *
329 * Perform basic initialization of a GPIO controller
330 *
331 * @param dev GPIO device struct
332 *
333 * @return 0
334 */
gpio_sifive_init(const struct device * dev)335 static int gpio_sifive_init(const struct device *dev)
336 {
337 volatile struct gpio_sifive_t *gpio = DEV_GPIO(dev);
338 const struct gpio_sifive_config *cfg = DEV_GPIO_CFG(dev);
339
340 /* Ensure that all gpio registers are reset to 0 initially */
341 gpio->in_en = 0U;
342 gpio->out_en = 0U;
343 gpio->pue = 0U;
344 gpio->rise_ie = 0U;
345 gpio->fall_ie = 0U;
346 gpio->high_ie = 0U;
347 gpio->low_ie = 0U;
348 gpio->iof_en = 0U;
349 gpio->iof_sel = 0U;
350 gpio->invert = 0U;
351
352 /* Setup IRQ handler for each gpio pin */
353 cfg->gpio_cfg_func();
354
355 return 0;
356 }
357
358 static void gpio_sifive_cfg_0(void);
359
360 static const struct gpio_sifive_config gpio_sifive_config0 = {
361 .common = {
362 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(0),
363 },
364 .gpio_base_addr = DT_INST_REG_ADDR(0),
365 .gpio_irq_base = DT_INST_IRQN(0),
366 .gpio_cfg_func = gpio_sifive_cfg_0,
367 };
368
369 static struct gpio_sifive_data gpio_sifive_data0;
370
371 DEVICE_DT_INST_DEFINE(0,
372 gpio_sifive_init,
373 NULL,
374 &gpio_sifive_data0, &gpio_sifive_config0,
375 PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY,
376 &gpio_sifive_driver);
377
378 #define IRQ_INIT(n) \
379 IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, n, irq), \
380 DT_INST_IRQ_BY_IDX(0, n, priority), \
381 gpio_sifive_irq_handler, \
382 DEVICE_DT_INST_GET(0), \
383 0);
384
gpio_sifive_cfg_0(void)385 static void gpio_sifive_cfg_0(void)
386 {
387 #if DT_INST_IRQ_HAS_IDX(0, 0)
388 IRQ_INIT(0);
389 #endif
390 #if DT_INST_IRQ_HAS_IDX(0, 1)
391 IRQ_INIT(1);
392 #endif
393 #if DT_INST_IRQ_HAS_IDX(0, 2)
394 IRQ_INIT(2);
395 #endif
396 #if DT_INST_IRQ_HAS_IDX(0, 3)
397 IRQ_INIT(3);
398 #endif
399 #if DT_INST_IRQ_HAS_IDX(0, 4)
400 IRQ_INIT(4);
401 #endif
402 #if DT_INST_IRQ_HAS_IDX(0, 5)
403 IRQ_INIT(5);
404 #endif
405 #if DT_INST_IRQ_HAS_IDX(0, 6)
406 IRQ_INIT(6);
407 #endif
408 #if DT_INST_IRQ_HAS_IDX(0, 7)
409 IRQ_INIT(7);
410 #endif
411 #if DT_INST_IRQ_HAS_IDX(0, 8)
412 IRQ_INIT(8);
413 #endif
414 #if DT_INST_IRQ_HAS_IDX(0, 9)
415 IRQ_INIT(9);
416 #endif
417 #if DT_INST_IRQ_HAS_IDX(0, 10)
418 IRQ_INIT(10);
419 #endif
420 #if DT_INST_IRQ_HAS_IDX(0, 11)
421 IRQ_INIT(11);
422 #endif
423 #if DT_INST_IRQ_HAS_IDX(0, 12)
424 IRQ_INIT(12);
425 #endif
426 #if DT_INST_IRQ_HAS_IDX(0, 13)
427 IRQ_INIT(13);
428 #endif
429 #if DT_INST_IRQ_HAS_IDX(0, 14)
430 IRQ_INIT(14);
431 #endif
432 #if DT_INST_IRQ_HAS_IDX(0, 15)
433 IRQ_INIT(15);
434 #endif
435 #if DT_INST_IRQ_HAS_IDX(0, 16)
436 IRQ_INIT(16);
437 #endif
438 #if DT_INST_IRQ_HAS_IDX(0, 17)
439 IRQ_INIT(17);
440 #endif
441 #if DT_INST_IRQ_HAS_IDX(0, 18)
442 IRQ_INIT(18);
443 #endif
444 #if DT_INST_IRQ_HAS_IDX(0, 19)
445 IRQ_INIT(19);
446 #endif
447 #if DT_INST_IRQ_HAS_IDX(0, 20)
448 IRQ_INIT(20);
449 #endif
450 #if DT_INST_IRQ_HAS_IDX(0, 21)
451 IRQ_INIT(21);
452 #endif
453 #if DT_INST_IRQ_HAS_IDX(0, 22)
454 IRQ_INIT(22);
455 #endif
456 #if DT_INST_IRQ_HAS_IDX(0, 23)
457 IRQ_INIT(23);
458 #endif
459 #if DT_INST_IRQ_HAS_IDX(0, 24)
460 IRQ_INIT(24);
461 #endif
462 #if DT_INST_IRQ_HAS_IDX(0, 25)
463 IRQ_INIT(25);
464 #endif
465 #if DT_INST_IRQ_HAS_IDX(0, 26)
466 IRQ_INIT(26);
467 #endif
468 #if DT_INST_IRQ_HAS_IDX(0, 27)
469 IRQ_INIT(27);
470 #endif
471 #if DT_INST_IRQ_HAS_IDX(0, 28)
472 IRQ_INIT(28);
473 #endif
474 #if DT_INST_IRQ_HAS_IDX(0, 29)
475 IRQ_INIT(29);
476 #endif
477 #if DT_INST_IRQ_HAS_IDX(0, 30)
478 IRQ_INIT(30);
479 #endif
480 #if DT_INST_IRQ_HAS_IDX(0, 31)
481 IRQ_INIT(31);
482 #endif
483 }
484