1 /*
2  * Copyright (c) 2015 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT snps_designware_gpio
8 
9 #include <errno.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/dt-bindings/gpio/snps-designware-gpio.h>
14 #include "gpio_dw.h"
15 #include <zephyr/drivers/gpio/gpio_utils.h>
16 
17 #include <zephyr/pm/device.h>
18 #include <zephyr/sys/sys_io.h>
19 #include <zephyr/init.h>
20 #include <zephyr/sys/util.h>
21 #include <zephyr/sys/__assert.h>
22 #include <zephyr/drivers/clock_control.h>
23 #include <zephyr/irq.h>
24 
25 #ifdef CONFIG_IOAPIC
26 #include <zephyr/drivers/interrupt_controller/ioapic.h>
27 #endif
28 
29 static int gpio_dw_port_set_bits_raw(const struct device *port, uint32_t mask);
30 static int gpio_dw_port_clear_bits_raw(const struct device *port,
31 				       uint32_t mask);
32 
33 /*
34  * ARC architecture configure IP through IO auxiliary registers.
35  * Other architectures as ARM and x86 configure IP through MMIO registers
36  */
37 #ifdef GPIO_DW_IO_ACCESS
dw_read(uint32_t base_addr,uint32_t offset)38 static inline uint32_t dw_read(uint32_t base_addr, uint32_t offset)
39 {
40 	return sys_in32(base_addr + offset);
41 }
42 
dw_write(uint32_t base_addr,uint32_t offset,uint32_t val)43 static inline void dw_write(uint32_t base_addr, uint32_t offset,
44 			    uint32_t val)
45 {
46 	sys_out32(val, base_addr + offset);
47 }
48 
dw_set_bit(uint32_t base_addr,uint32_t offset,uint32_t bit,bool value)49 static void dw_set_bit(uint32_t base_addr, uint32_t offset,
50 		       uint32_t bit, bool value)
51 {
52 	if (!value) {
53 		sys_io_clear_bit(base_addr + offset, bit);
54 	} else {
55 		sys_io_set_bit(base_addr + offset, bit);
56 	}
57 }
58 #else
dw_read(uint32_t base_addr,uint32_t offset)59 static inline uint32_t dw_read(uint32_t base_addr, uint32_t offset)
60 {
61 	return sys_read32(base_addr + offset);
62 }
63 
dw_write(uint32_t base_addr,uint32_t offset,uint32_t val)64 static inline void dw_write(uint32_t base_addr, uint32_t offset,
65 			    uint32_t val)
66 {
67 	sys_write32(val, base_addr + offset);
68 }
69 
dw_set_bit(uint32_t base_addr,uint32_t offset,uint32_t bit,bool value)70 static void dw_set_bit(uint32_t base_addr, uint32_t offset,
71 		       uint32_t bit, bool value)
72 {
73 	if (!value) {
74 		sys_clear_bit(base_addr + offset, bit);
75 	} else {
76 		sys_set_bit(base_addr + offset, bit);
77 	}
78 }
79 #endif
80 
dw_base_to_block_base(uint32_t base_addr)81 static inline int dw_base_to_block_base(uint32_t base_addr)
82 {
83 	return (base_addr & 0xFFFFFFC0);
84 }
85 
dw_derive_port_from_base(uint32_t base_addr)86 static inline int dw_derive_port_from_base(uint32_t base_addr)
87 {
88 	uint32_t port = (base_addr & 0x3f) / 12U;
89 	return port;
90 }
91 
dw_interrupt_support(const struct gpio_dw_config * config)92 static inline int dw_interrupt_support(const struct gpio_dw_config *config)
93 {
94 	return ((int)(config->irq_num) > 0U);
95 }
96 
dw_get_ext_port(uint32_t base_addr)97 static inline uint32_t dw_get_ext_port(uint32_t base_addr)
98 {
99 	uint32_t ext_port;
100 
101 	/* 4-port GPIO implementation translates from base address to port */
102 	switch (dw_derive_port_from_base(base_addr)) {
103 	case 1:
104 		ext_port = EXT_PORTB;
105 		break;
106 	case 2:
107 		ext_port = EXT_PORTC;
108 		break;
109 	case 3:
110 		ext_port = EXT_PORTD;
111 		break;
112 	case 0:
113 	default:
114 		ext_port = EXT_PORTA;
115 		break;
116 	}
117 
118 	return ext_port;
119 }
120 
dw_get_data_port(uint32_t base_addr)121 static inline uint32_t dw_get_data_port(uint32_t base_addr)
122 {
123 	uint32_t dr_port;
124 
125 	/* 4-port GPIO implementation translates from base address to port */
126 	switch (dw_derive_port_from_base(base_addr)) {
127 	case 1:
128 		dr_port = SWPORTB_DR;
129 		break;
130 	case 2:
131 		dr_port = SWPORTC_DR;
132 		break;
133 	case 3:
134 		dr_port = SWPORTD_DR;
135 		break;
136 	case 0:
137 	default:
138 		dr_port = SWPORTA_DR;
139 		break;
140 	}
141 
142 	return dr_port;
143 }
144 
dw_get_dir_port(uint32_t base_addr)145 static inline uint32_t dw_get_dir_port(uint32_t base_addr)
146 {
147 	uint32_t ddr_port;
148 
149 	/* 4-port GPIO implementation translates from base address to port */
150 	switch (dw_derive_port_from_base(base_addr)) {
151 	case 1:
152 		ddr_port = SWPORTB_DDR;
153 		break;
154 	case 2:
155 		ddr_port = SWPORTC_DDR;
156 		break;
157 	case 3:
158 		ddr_port = SWPORTD_DDR;
159 		break;
160 	case 0:
161 	default:
162 		ddr_port = SWPORTA_DDR;
163 		break;
164 	}
165 
166 	return ddr_port;
167 }
168 
gpio_dw_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)169 static int gpio_dw_pin_interrupt_configure(const struct device *port,
170 					   gpio_pin_t pin,
171 					   enum gpio_int_mode mode,
172 					   enum gpio_int_trig trig)
173 {
174 	struct gpio_dw_runtime *context = port->data;
175 	const struct gpio_dw_config *config = port->config;
176 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
177 	uint32_t port_base_addr = context->base_addr;
178 	uint32_t dir_port = dw_get_dir_port(port_base_addr);
179 	uint32_t data_port = dw_get_data_port(port_base_addr);
180 	uint32_t dir_reg;
181 
182 	/* Check for invalid pin number */
183 	if (pin >= config->ngpios) {
184 		return -EINVAL;
185 	}
186 
187 	/* Only PORT-A supports interrupts */
188 	if (data_port != SWPORTA_DR) {
189 		return -ENOTSUP;
190 	}
191 
192 	if (mode != GPIO_INT_MODE_DISABLED) {
193 		/* Check if GPIO port supports interrupts */
194 		if (!dw_interrupt_support(config)) {
195 			return -ENOTSUP;
196 		}
197 
198 		/* Interrupt to be enabled but pin is not set to input */
199 		dir_reg = dw_read(base_addr, dir_port) & BIT(pin);
200 		if (dir_reg != 0U) {
201 			return -EINVAL;
202 		}
203 	}
204 
205 	/* Does not support both edges */
206 	if ((mode == GPIO_INT_MODE_EDGE) &&
207 	    (trig == GPIO_INT_TRIG_BOTH)) {
208 		return -ENOTSUP;
209 	}
210 
211 	/* Clear interrupt enable */
212 	dw_set_bit(base_addr, INTEN, pin, false);
213 
214 	/* Mask and clear interrupt */
215 	dw_set_bit(base_addr, INTMASK, pin, true);
216 	dw_write(base_addr, PORTA_EOI, BIT(pin));
217 
218 	if (mode != GPIO_INT_MODE_DISABLED) {
219 		/* level (0) or edge (1) */
220 		dw_set_bit(base_addr, INTTYPE_LEVEL, pin,
221 			   (mode == GPIO_INT_MODE_EDGE));
222 
223 		/* Active low/high */
224 		dw_set_bit(base_addr, INT_POLARITY, pin,
225 			   (trig == GPIO_INT_TRIG_HIGH));
226 
227 		/* Finally enabling interrupt */
228 		dw_set_bit(base_addr, INTEN, pin, true);
229 		dw_set_bit(base_addr, INTMASK, pin, false);
230 	}
231 
232 	return 0;
233 }
234 
dw_pin_config(const struct device * port,uint32_t pin,int flags)235 static inline void dw_pin_config(const struct device *port,
236 				 uint32_t pin, int flags)
237 {
238 	struct gpio_dw_runtime *context = port->data;
239 	const struct gpio_dw_config *config = port->config;
240 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
241 	uint32_t port_base_addr = context->base_addr;
242 	uint32_t dir_port = dw_get_dir_port(port_base_addr);
243 	bool pin_is_output, need_debounce;
244 
245 	/* Set init value then direction */
246 	pin_is_output = (flags & GPIO_OUTPUT) != 0U;
247 
248 	dw_set_bit(base_addr, dir_port, pin, pin_is_output);
249 
250 	if (pin_is_output) {
251 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
252 			gpio_dw_port_set_bits_raw(port, BIT(pin));
253 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
254 			gpio_dw_port_clear_bits_raw(port, BIT(pin));
255 		}
256 	}
257 
258 	/* Use built-in debounce.
259 	 * Note debounce circuit is only available if also supporting
260 	 * interrupts according to datasheet.
261 	 */
262 	if (dw_interrupt_support(config) && (dir_port == SWPORTA_DDR)) {
263 		need_debounce = (flags & DW_GPIO_DEBOUNCE);
264 		dw_set_bit(base_addr, PORTA_DEBOUNCE, pin, need_debounce);
265 	}
266 }
267 
gpio_dw_config(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)268 static inline int gpio_dw_config(const struct device *port,
269 				 gpio_pin_t pin,
270 				 gpio_flags_t flags)
271 {
272 	const struct gpio_dw_config *config = port->config;
273 	uint32_t io_flags;
274 
275 	/* Check for invalid pin number */
276 	if (pin >= config->ngpios) {
277 		return -EINVAL;
278 	}
279 
280 	/* Does not support disconnected pin, and
281 	 * not supporting both input/output at same time.
282 	 */
283 	io_flags = flags & (GPIO_INPUT | GPIO_OUTPUT);
284 	if ((io_flags == GPIO_DISCONNECTED)
285 	    || (io_flags == (GPIO_INPUT | GPIO_OUTPUT))) {
286 		return -ENOTSUP;
287 	}
288 
289 	/* No open-drain support */
290 	if ((flags & GPIO_SINGLE_ENDED) != 0U) {
291 		return -ENOTSUP;
292 	}
293 
294 	/* Does not support pull-up/pull-down */
295 	if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0U) {
296 		return -ENOTSUP;
297 	}
298 
299 	dw_pin_config(port, pin, flags);
300 
301 	return 0;
302 }
303 
gpio_dw_port_get_raw(const struct device * port,uint32_t * value)304 static int gpio_dw_port_get_raw(const struct device *port, uint32_t *value)
305 {
306 	struct gpio_dw_runtime *context = port->data;
307 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
308 	uint32_t port_base_addr = context->base_addr;
309 	uint32_t ext_port = dw_get_ext_port(port_base_addr);
310 
311 	*value = dw_read(base_addr, ext_port);
312 
313 	return 0;
314 }
315 
gpio_dw_port_set_masked_raw(const struct device * port,uint32_t mask,uint32_t value)316 static int gpio_dw_port_set_masked_raw(const struct device *port,
317 				       uint32_t mask, uint32_t value)
318 {
319 	struct gpio_dw_runtime *context = port->data;
320 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
321 	uint32_t port_base_addr = context->base_addr;
322 	uint32_t data_port = dw_get_data_port(port_base_addr);
323 	uint32_t pins;
324 
325 	pins = dw_read(base_addr, data_port);
326 	pins = (pins & ~mask) | (mask & value);
327 	dw_write(base_addr, data_port, pins);
328 
329 	return 0;
330 }
331 
gpio_dw_port_set_bits_raw(const struct device * port,uint32_t mask)332 static int gpio_dw_port_set_bits_raw(const struct device *port, uint32_t mask)
333 {
334 	struct gpio_dw_runtime *context = port->data;
335 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
336 	uint32_t port_base_addr = context->base_addr;
337 	uint32_t data_port = dw_get_data_port(port_base_addr);
338 	uint32_t pins;
339 
340 	pins = dw_read(base_addr, data_port);
341 	pins |= mask;
342 	dw_write(base_addr, data_port, pins);
343 
344 	return 0;
345 }
346 
gpio_dw_port_clear_bits_raw(const struct device * port,uint32_t mask)347 static int gpio_dw_port_clear_bits_raw(const struct device *port,
348 				       uint32_t mask)
349 {
350 	struct gpio_dw_runtime *context = port->data;
351 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
352 	uint32_t port_base_addr = context->base_addr;
353 	uint32_t data_port = dw_get_data_port(port_base_addr);
354 	uint32_t pins;
355 
356 	pins = dw_read(base_addr, data_port);
357 	pins &= ~mask;
358 	dw_write(base_addr, data_port, pins);
359 
360 	return 0;
361 }
362 
gpio_dw_port_toggle_bits(const struct device * port,uint32_t mask)363 static int gpio_dw_port_toggle_bits(const struct device *port, uint32_t mask)
364 {
365 	struct gpio_dw_runtime *context = port->data;
366 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
367 	uint32_t port_base_addr = context->base_addr;
368 	uint32_t data_port = dw_get_data_port(port_base_addr);
369 	uint32_t pins;
370 
371 	pins = dw_read(base_addr, data_port);
372 	pins ^= mask;
373 	dw_write(base_addr, data_port, pins);
374 
375 	return 0;
376 }
377 
gpio_dw_manage_callback(const struct device * port,struct gpio_callback * callback,bool set)378 static inline int gpio_dw_manage_callback(const struct device *port,
379 					  struct gpio_callback *callback,
380 					  bool set)
381 {
382 	struct gpio_dw_runtime *context = port->data;
383 
384 	return gpio_manage_callback(&context->callbacks, callback, set);
385 }
386 
gpio_dw_isr(const struct device * port)387 static void gpio_dw_isr(const struct device *port)
388 {
389 	struct gpio_dw_runtime *context = port->data;
390 	uint32_t base_addr = dw_base_to_block_base(context->base_addr);
391 	uint32_t int_status;
392 
393 	int_status = dw_read(base_addr, INTSTATUS);
394 
395 	dw_write(base_addr, PORTA_EOI, int_status);
396 
397 	gpio_fire_callbacks(&context->callbacks, port, int_status);
398 }
399 
400 static const struct gpio_driver_api api_funcs = {
401 	.pin_configure = gpio_dw_config,
402 	.port_get_raw = gpio_dw_port_get_raw,
403 	.port_set_masked_raw = gpio_dw_port_set_masked_raw,
404 	.port_set_bits_raw = gpio_dw_port_set_bits_raw,
405 	.port_clear_bits_raw = gpio_dw_port_clear_bits_raw,
406 	.port_toggle_bits = gpio_dw_port_toggle_bits,
407 	.pin_interrupt_configure = gpio_dw_pin_interrupt_configure,
408 	.manage_callback = gpio_dw_manage_callback,
409 };
410 
gpio_dw_initialize(const struct device * port)411 static int gpio_dw_initialize(const struct device *port)
412 {
413 	struct gpio_dw_runtime *context = port->data;
414 	const struct gpio_dw_config *config = port->config;
415 	uint32_t base_addr;
416 
417 	if (dw_interrupt_support(config)) {
418 
419 		base_addr = dw_base_to_block_base(context->base_addr);
420 
421 		/* interrupts in sync with system clock */
422 		dw_set_bit(base_addr, INT_CLOCK_SYNC, LS_SYNC_POS, 1);
423 
424 		/* mask and disable interrupts */
425 		dw_write(base_addr, INTMASK, ~(0));
426 		dw_write(base_addr, INTEN, 0);
427 		dw_write(base_addr, PORTA_EOI, ~(0));
428 
429 		config->config_func(port);
430 	}
431 
432 	return 0;
433 }
434 
435 /* Bindings to the platform */
436 #define INST_IRQ_FLAGS(n) \
437 	COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, flags), (DT_INST_IRQ(n, flags)), (0))
438 
439 #define GPIO_CFG_IRQ(idx, n)									\
440 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq),					\
441 			    DT_INST_IRQ(n, priority), gpio_dw_isr,				\
442 			    DEVICE_DT_INST_GET(n), INST_IRQ_FLAGS(n));				\
443 		irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq));					\
444 
445 #define GPIO_DW_INIT(n)										\
446 	static void gpio_config_##n##_irq(const struct device *port)				\
447 	{											\
448 		ARG_UNUSED(port);			                                        \
449 		LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), GPIO_CFG_IRQ, (), n)                       \
450 	}											\
451 												\
452 	static const struct gpio_dw_config gpio_dw_config_##n = {				\
453 		.common = {									\
454 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),			\
455 		},										\
456 		.irq_num = COND_CODE_1(DT_INST_IRQ_HAS_IDX(n, 0), (DT_INST_IRQN(n)), (0)),	\
457 		.ngpios = DT_INST_PROP(n, ngpios),						\
458 		.config_func = gpio_config_##n##_irq,						\
459 	};											\
460 												\
461 	static struct gpio_dw_runtime gpio_##n##_runtime = {					\
462 		.base_addr = DT_INST_REG_ADDR(n),						\
463 	};											\
464 												\
465 	DEVICE_DT_INST_DEFINE(n, gpio_dw_initialize, NULL, &gpio_##n##_runtime,			\
466 		      &gpio_dw_config_##n, PRE_KERNEL_1,					\
467 		      CONFIG_GPIO_INIT_PRIORITY, &api_funcs);					\
468 
469 DT_INST_FOREACH_STATUS_OKAY(GPIO_DW_INIT)
470