1 /*
2  * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 /** @file
7  * @brief Atmel SAM MCU family General-Purpose Input/Output Controller (GPIO)
8  * module HAL driver.
9  */
10 
11 #include <zephyr/sys/__assert.h>
12 #include "soc_gpio.h"
13 
configure_common_attr(volatile Gpio * gpio,uint32_t mask,uint32_t flags)14 static void configure_common_attr(volatile Gpio *gpio,
15 				  uint32_t mask, uint32_t flags)
16 {
17 	flags &= SOC_GPIO_FLAGS_MASK;
18 
19 	/* Disable interrupts on the pin(s) */
20 	gpio->IERC = mask;
21 
22 	/* Configure pull-up(s) */
23 	if (flags & SOC_GPIO_PULLUP) {
24 		gpio->PUERS = mask;
25 	} else {
26 		gpio->PUERC = mask;
27 	}
28 
29 	/* Configure pull-down(s) */
30 	if (flags & SOC_GPIO_PULLDOWN) {
31 		gpio->PDERS = mask;
32 	} else {
33 		gpio->PDERC = mask;
34 	}
35 
36 	/* Configure open drain (multi-drive) */
37 	if (flags & SOC_GPIO_OPENDRAIN) {
38 		gpio->ODMERS = mask;
39 	} else {
40 		gpio->ODMERC = mask;
41 	}
42 }
43 
configure_input_attr(volatile Gpio * gpio,uint32_t mask,uint32_t flags)44 static void configure_input_attr(volatile Gpio *gpio,
45 				 uint32_t mask, uint32_t flags)
46 {
47 	/* Configure input filter */
48 	if ((flags & SOC_GPIO_IN_FILTER_MASK) != 0U) {
49 		if ((flags & SOC_GPIO_IN_FILTER_MASK) ==
50 		    SOC_GPIO_IN_FILTER_DEBOUNCE) {
51 			/* Enable de-bounce, disable de-glitch */
52 			gpio->GFERC = mask;
53 		} else {
54 			/* Disable de-bounce, enable de-glitch */
55 			gpio->GFERS = mask;
56 		}
57 	} else {
58 		gpio->GFERC = mask;
59 	}
60 
61 	/* Configure interrupt */
62 	if (flags & SOC_GPIO_INT_ENABLE) {
63 		if ((flags & SOC_GPIO_INT_TRIG_MASK) ==
64 		    SOC_GPIO_INT_TRIG_DOUBLE_EDGE) {
65 			gpio->IMR0C = mask;
66 			gpio->IMR1C = mask;
67 		} else {
68 			if (flags & SOC_GPIO_INT_ACTIVE_HIGH) {
69 				/* Rising Edge*/
70 				gpio->IMR0S = mask;
71 				gpio->IMR1C = mask;
72 			} else {
73 				/* Falling Edge */
74 				gpio->IMR0C = mask;
75 				gpio->IMR1S = mask;
76 			}
77 		}
78 		/* Enable interrupts on the pin(s) */
79 		gpio->IERS = mask;
80 	} else {
81 		gpio->IERC = mask;
82 	}
83 }
84 
soc_gpio_configure(const struct soc_gpio_pin * pin)85 void soc_gpio_configure(const struct soc_gpio_pin *pin)
86 {
87 	uint32_t mask = pin->mask;
88 	volatile Gpio *gpio = pin->regs;
89 	uint8_t periph_id = pin->periph_id;
90 	uint32_t flags = pin->flags;
91 	uint32_t type = pin->flags & SOC_GPIO_FUNC_MASK;
92 
93 	/* Configure pin attributes common to all functions */
94 	configure_common_attr(gpio, mask, flags);
95 
96 	switch (type) {
97 	case SOC_GPIO_FUNC_A:
98 		gpio->PMR0C = mask;
99 		gpio->PMR1C = mask;
100 		gpio->PMR2C = mask;
101 		gpio->GPERC = mask;
102 		break;
103 
104 	case SOC_GPIO_FUNC_B:
105 		gpio->PMR0S = mask;
106 		gpio->PMR1C = mask;
107 		gpio->PMR2C = mask;
108 		gpio->GPERC = mask;
109 		break;
110 
111 	case SOC_GPIO_FUNC_C:
112 		gpio->PMR0C = mask;
113 		gpio->PMR1S = mask;
114 		gpio->PMR2C = mask;
115 		gpio->GPERC = mask;
116 		break;
117 
118 	case SOC_GPIO_FUNC_D:
119 		gpio->PMR0S = mask;
120 		gpio->PMR1S = mask;
121 		gpio->PMR2C = mask;
122 		gpio->GPERC = mask;
123 		break;
124 
125 	case SOC_GPIO_FUNC_E:
126 		gpio->PMR0C = mask;
127 		gpio->PMR1C = mask;
128 		gpio->PMR2S = mask;
129 		gpio->GPERC = mask;
130 		break;
131 
132 	case SOC_GPIO_FUNC_F:
133 		gpio->PMR0S = mask;
134 		gpio->PMR1C = mask;
135 		gpio->PMR2S = mask;
136 		gpio->GPERC = mask;
137 		break;
138 
139 	case SOC_GPIO_FUNC_G:
140 		gpio->PMR0C = mask;
141 		gpio->PMR1S = mask;
142 		gpio->PMR2S = mask;
143 		gpio->GPERC = mask;
144 		break;
145 
146 	case SOC_GPIO_FUNC_H:
147 		gpio->PMR0S = mask;
148 		gpio->PMR1S = mask;
149 		gpio->PMR2S = mask;
150 		gpio->GPERC = mask;
151 		break;
152 
153 	case SOC_GPIO_FUNC_IN:
154 		soc_pmc_peripheral_enable(periph_id);
155 		configure_input_attr(gpio, mask, flags);
156 
157 		gpio->ODERC = mask;
158 		gpio->STERS = mask;
159 		gpio->GPERS = mask;
160 		break;
161 
162 	case SOC_GPIO_FUNC_OUT_1:
163 	case SOC_GPIO_FUNC_OUT_0:
164 		if (type == SOC_GPIO_FUNC_OUT_1) {
165 			gpio->OVRS = mask;
166 		} else {
167 			gpio->OVRC = mask;
168 		}
169 
170 		gpio->ODCR0S = mask;
171 		gpio->ODCR1S = mask;
172 		gpio->ODERS = mask;
173 		gpio->STERC = mask;
174 		gpio->GPERS = mask;
175 		break;
176 
177 	default:
178 		__ASSERT(0, "Unsupported pin function, check pin.flags value");
179 		return;
180 	}
181 }
182 
soc_gpio_list_configure(const struct soc_gpio_pin pins[],unsigned int size)183 void soc_gpio_list_configure(const struct soc_gpio_pin pins[],
184 			     unsigned int size)
185 {
186 	for (int i = 0; i < size; i++) {
187 		soc_gpio_configure(&pins[i]);
188 	}
189 }
190