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