1 /*
2  * Copyright (c) 2017, Christian Taedcke
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT silabs_gecko_gpio_port
8 
9 #include <errno.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/sys/util.h>
13 #include <soc.h>
14 #include <em_gpio.h>
15 #ifdef CONFIG_SOC_GECKO_DEV_INIT
16 #include <em_cmu.h>
17 #endif
18 
19 #include <zephyr/drivers/gpio/gpio_utils.h>
20 
21 #if CONFIG_GPIO_GECKO_COMMON_INIT_PRIORITY >= CONFIG_GPIO_INIT_PRIORITY
22 #error CONFIG_GPIO_GECKO_COMMON_INIT_PRIORITY must be less than \
23 	CONFIG_GPIO_INIT_PRIORITY.
24 #endif
25 
26 #if DT_NODE_HAS_PROP(id, peripheral_id)
27 #define GET_GECKO_GPIO_INDEX(id) DT_INST_PROP(id, peripheral_id)
28 #else
29 #if defined(CONFIG_SOC_SERIES_EFR32BG22) || \
30 	defined(CONFIG_SOC_SERIES_EFR32BG27) || \
31 	defined(CONFIG_SOC_SERIES_EFR32MG21) || \
32 	defined(CONFIG_SOC_SERIES_EFR32MG24) || \
33 	defined(CONFIG_SOC_SERIES_EFR32ZG23)
34 #define GECKO_GPIO_PORT_ADDR_SPACE_SIZE sizeof(GPIO_PORT_TypeDef)
35 #else
36 #define GECKO_GPIO_PORT_ADDR_SPACE_SIZE sizeof(GPIO_P_TypeDef)
37 #endif
38 /* Assumption for calculating gpio index:
39  * 1. Address space of the first GPIO port is the address space for GPIO port A
40  */
41 #define GET_GECKO_GPIO_INDEX(id) (DT_INST_REG_ADDR(id) - DT_REG_ADDR(DT_NODELABEL(gpioa))) \
42 	/ GECKO_GPIO_PORT_ADDR_SPACE_SIZE
43 #endif /* DT_NODE_HAS_PROP(id, peripheral_id) */
44 
45 /*
46  * Macros to set the GPIO MODE registers
47  *
48  * See https://www.silabs.com/documents/public/reference-manuals/EFM32WG-RM.pdf
49  * pages 972 and 982.
50  */
51 /**
52  * @brief Create the value to set the GPIO MODEL register
53  * @param[in] pin The index of the pin. Valid values are 0..7.
54  * @param[in] mode The mode that should be set.
55  * @return The value that can be set into the GPIO MODEL register.
56  */
57 #define GECKO_GPIO_MODEL(pin, mode) (mode << (pin * 4))
58 
59 /**
60  * @brief Create the value to set the GPIO MODEH register
61  * @param[in] pin The index of the pin. Valid values are 8..15.
62  * @param[in] mode The mode that should be set.
63  * @return The value that can be set into the GPIO MODEH register.
64  */
65 #define GECKO_GPIO_MODEH(pin, mode) (mode << ((pin - 8) * 4))
66 
67 
68 #define NUMBER_OF_PORTS (SIZEOF_FIELD(GPIO_TypeDef, P) / \
69 			 SIZEOF_FIELD(GPIO_TypeDef, P[0]))
70 
71 struct gpio_gecko_common_config {
72 };
73 
74 struct gpio_gecko_common_data {
75 	/* a list of all ports */
76 	const struct device *ports[NUMBER_OF_PORTS];
77 	size_t count;
78 };
79 
80 struct gpio_gecko_config {
81 	/* gpio_driver_config needs to be first */
82 	struct gpio_driver_config common;
83 	GPIO_Port_TypeDef gpio_index;
84 };
85 
86 struct gpio_gecko_data {
87 	/* gpio_driver_data needs to be first */
88 	struct gpio_driver_data common;
89 	/* port ISR callback routine address */
90 	sys_slist_t callbacks;
91 	/* mask of pins on which interrupt is enabled */
92 	uint32_t int_enabled_mask;
93 };
94 
gpio_gecko_add_port(struct gpio_gecko_common_data * data,const struct device * dev)95 static inline void gpio_gecko_add_port(struct gpio_gecko_common_data *data,
96 				       const struct device *dev)
97 {
98 	__ASSERT(dev, "No port device!");
99 	data->ports[data->count++] = dev;
100 }
101 
gpio_gecko_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)102 static int gpio_gecko_configure(const struct device *dev,
103 				gpio_pin_t pin,
104 				gpio_flags_t flags)
105 {
106 	const struct gpio_gecko_config *config = dev->config;
107 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
108 	GPIO_Mode_TypeDef mode;
109 	unsigned int out = 0U;
110 
111 	if (flags & GPIO_OUTPUT) {
112 		/* Following modes enable both output and input */
113 		if (flags & GPIO_SINGLE_ENDED) {
114 			if (flags & GPIO_LINE_OPEN_DRAIN) {
115 				mode = gpioModeWiredAnd;
116 			} else {
117 				mode = gpioModeWiredOr;
118 			}
119 		} else {
120 			mode = gpioModePushPull;
121 		}
122 		if (flags & GPIO_OUTPUT_INIT_HIGH) {
123 			out = 1U;
124 		} else if (flags & GPIO_OUTPUT_INIT_LOW) {
125 			out = 0U;
126 		} else {
127 			out = GPIO_PinOutGet(gpio_index, pin);
128 		}
129 	} else if (flags & GPIO_INPUT) {
130 		if (flags & GPIO_PULL_UP) {
131 			mode = gpioModeInputPull;
132 			out = 1U; /* pull-up*/
133 		} else if (flags & GPIO_PULL_DOWN) {
134 			mode = gpioModeInputPull;
135 			/* out = 0 means pull-down*/
136 		} else {
137 			mode = gpioModeInput;
138 		}
139 	} else {
140 		/* Neither input nor output mode is selected */
141 		mode = gpioModeDisabled;
142 	}
143 	/* The flags contain options that require touching registers in the
144 	 * GPIO module and the corresponding PORT module.
145 	 *
146 	 * Start with the GPIO module and set up the pin direction register.
147 	 * 0 - pin is input, 1 - pin is output
148 	 */
149 
150 	GPIO_PinModeSet(gpio_index, pin, mode, out);
151 
152 	return 0;
153 }
154 
155 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_gecko_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * out_flags)156 static int gpio_gecko_get_config(const struct device *dev,
157 				 gpio_pin_t pin,
158 				 gpio_flags_t *out_flags)
159 {
160 	const struct gpio_gecko_config *config = dev->config;
161 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
162 	GPIO_Mode_TypeDef mode;
163 	unsigned int out;
164 	gpio_flags_t flags = 0;
165 
166 	mode = GPIO_PinModeGet(gpio_index, pin);
167 	out = GPIO_PinOutGet(gpio_index, pin);
168 
169 	switch (mode) {
170 	case gpioModeWiredAnd:
171 		flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN;
172 
173 		if (out) {
174 			flags |= GPIO_OUTPUT_HIGH;
175 		} else {
176 			flags |= GPIO_OUTPUT_LOW;
177 		}
178 
179 		break;
180 	case gpioModeWiredOr:
181 		flags = GPIO_OUTPUT | GPIO_OPEN_SOURCE;
182 
183 		if (out) {
184 			flags |= GPIO_OUTPUT_HIGH;
185 		} else {
186 			flags |= GPIO_OUTPUT_LOW;
187 		}
188 
189 		break;
190 	case gpioModePushPull:
191 		flags = GPIO_OUTPUT | GPIO_PUSH_PULL;
192 
193 		if (out) {
194 			flags |= GPIO_OUTPUT_HIGH;
195 		} else {
196 			flags |= GPIO_OUTPUT_LOW;
197 		}
198 
199 		break;
200 	case gpioModeInputPull:
201 		flags = GPIO_INPUT;
202 
203 		if (out) {
204 			flags |= GPIO_PULL_UP;
205 		} else {
206 			flags |= GPIO_PULL_DOWN;
207 		}
208 
209 		break;
210 	case gpioModeInput:
211 		flags = GPIO_INPUT;
212 		break;
213 	case gpioModeDisabled:
214 		flags = GPIO_DISCONNECTED;
215 		break;
216 	default:
217 		break;
218 	}
219 
220 	*out_flags = flags;
221 
222 	return 0;
223 }
224 #endif
225 
gpio_gecko_port_get_raw(const struct device * dev,uint32_t * value)226 static int gpio_gecko_port_get_raw(const struct device *dev, uint32_t *value)
227 {
228 	const struct gpio_gecko_config *config = dev->config;
229 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
230 
231 	*value = GPIO_PortInGet(gpio_index);
232 
233 	return 0;
234 }
235 
gpio_gecko_port_set_masked_raw(const struct device * dev,uint32_t mask,uint32_t value)236 static int gpio_gecko_port_set_masked_raw(const struct device *dev,
237 					  uint32_t mask,
238 					  uint32_t value)
239 {
240 	const struct gpio_gecko_config *config = dev->config;
241 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
242 
243 	GPIO_PortOutSetVal(gpio_index, value, mask);
244 
245 	return 0;
246 }
247 
gpio_gecko_port_set_bits_raw(const struct device * dev,uint32_t mask)248 static int gpio_gecko_port_set_bits_raw(const struct device *dev,
249 					uint32_t mask)
250 {
251 	const struct gpio_gecko_config *config = dev->config;
252 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
253 
254 	GPIO_PortOutSet(gpio_index, mask);
255 
256 	return 0;
257 }
258 
gpio_gecko_port_clear_bits_raw(const struct device * dev,uint32_t mask)259 static int gpio_gecko_port_clear_bits_raw(const struct device *dev,
260 					  uint32_t mask)
261 {
262 	const struct gpio_gecko_config *config = dev->config;
263 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
264 
265 	GPIO_PortOutClear(gpio_index, mask);
266 
267 	return 0;
268 }
269 
gpio_gecko_port_toggle_bits(const struct device * dev,uint32_t mask)270 static int gpio_gecko_port_toggle_bits(const struct device *dev,
271 				       uint32_t mask)
272 {
273 	const struct gpio_gecko_config *config = dev->config;
274 	GPIO_Port_TypeDef gpio_index = config->gpio_index;
275 
276 	GPIO_PortOutToggle(gpio_index, mask);
277 
278 	return 0;
279 }
280 
gpio_gecko_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)281 static int gpio_gecko_pin_interrupt_configure(const struct device *dev,
282 					      gpio_pin_t pin,
283 					      enum gpio_int_mode mode,
284 					      enum gpio_int_trig trig)
285 {
286 	const struct gpio_gecko_config *config = dev->config;
287 	struct gpio_gecko_data *data = dev->data;
288 
289 	/* Interrupt on static level is not supported by the hardware */
290 	if (mode == GPIO_INT_MODE_LEVEL) {
291 		return -ENOTSUP;
292 	}
293 
294 	if (mode == GPIO_INT_MODE_DISABLED) {
295 		GPIO_IntDisable(BIT(pin));
296 	} else {
297 		/* Interrupt line is already in use */
298 		if ((GPIO->IEN & BIT(pin)) != 0) {
299 			/* TODO: Return an error only if request is done for
300 			 * a pin from a different port.
301 			 */
302 			return -EBUSY;
303 		}
304 
305 		bool rising_edge = true;
306 		bool falling_edge = true;
307 
308 		if (trig == GPIO_INT_TRIG_LOW) {
309 			rising_edge = false;
310 			falling_edge = true;
311 		} else if (trig == GPIO_INT_TRIG_HIGH) {
312 			rising_edge = true;
313 			falling_edge = false;
314 		} /* default is GPIO_INT_TRIG_BOTH */
315 
316 		GPIO_ExtIntConfig(config->gpio_index, pin, pin,
317 			       rising_edge, falling_edge, true);
318 	}
319 
320 	WRITE_BIT(data->int_enabled_mask, pin, mode != GPIO_INT_DISABLE);
321 
322 	return 0;
323 }
324 
gpio_gecko_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)325 static int gpio_gecko_manage_callback(const struct device *dev,
326 				      struct gpio_callback *callback, bool set)
327 {
328 	struct gpio_gecko_data *data = dev->data;
329 
330 	return gpio_manage_callback(&data->callbacks, callback, set);
331 }
332 
333 /**
334  * Handler for both odd and even pin interrupts
335  */
gpio_gecko_common_isr(const struct device * dev)336 static void gpio_gecko_common_isr(const struct device *dev)
337 {
338 	struct gpio_gecko_common_data *data = dev->data;
339 	uint32_t enabled_int, int_status;
340 	const struct device *port_dev;
341 	struct gpio_gecko_data *port_data;
342 
343 	int_status = GPIO->IF;
344 
345 	for (unsigned int i = 0; int_status && (i < data->count); i++) {
346 		port_dev = data->ports[i];
347 		port_data = port_dev->data;
348 		enabled_int = int_status & port_data->int_enabled_mask;
349 		if (enabled_int != 0) {
350 			int_status &= ~enabled_int;
351 #if defined(_SILICON_LABS_32B_SERIES_2)
352 			GPIO->IF_CLR = enabled_int;
353 #else
354 			GPIO->IFC = enabled_int;
355 #endif
356 			gpio_fire_callbacks(&port_data->callbacks, port_dev,
357 					    enabled_int);
358 		}
359 	}
360 }
361 
362 static DEVICE_API(gpio, gpio_gecko_driver_api) = {
363 	.pin_configure = gpio_gecko_configure,
364 #ifdef CONFIG_GPIO_GET_CONFIG
365 	.pin_get_config = gpio_gecko_get_config,
366 #endif
367 	.port_get_raw = gpio_gecko_port_get_raw,
368 	.port_set_masked_raw = gpio_gecko_port_set_masked_raw,
369 	.port_set_bits_raw = gpio_gecko_port_set_bits_raw,
370 	.port_clear_bits_raw = gpio_gecko_port_clear_bits_raw,
371 	.port_toggle_bits = gpio_gecko_port_toggle_bits,
372 	.pin_interrupt_configure = gpio_gecko_pin_interrupt_configure,
373 	.manage_callback = gpio_gecko_manage_callback,
374 };
375 
376 static DEVICE_API(gpio, gpio_gecko_common_driver_api) = {
377 	.manage_callback = gpio_gecko_manage_callback,
378 };
379 
380 static int gpio_gecko_common_init(const struct device *dev);
381 
382 static const struct gpio_gecko_common_config gpio_gecko_common_config = {
383 };
384 
385 static struct gpio_gecko_common_data gpio_gecko_common_data;
386 
387 DEVICE_DT_DEFINE(DT_INST(0, silabs_gecko_gpio),
388 		    gpio_gecko_common_init,
389 		    NULL,
390 		    &gpio_gecko_common_data, &gpio_gecko_common_config,
391 		    PRE_KERNEL_1, CONFIG_GPIO_GECKO_COMMON_INIT_PRIORITY,
392 		    &gpio_gecko_common_driver_api);
393 
gpio_gecko_common_init(const struct device * dev)394 static int gpio_gecko_common_init(const struct device *dev)
395 {
396 #ifdef CONFIG_SOC_GECKO_DEV_INIT
397 	CMU_ClockEnable(cmuClock_GPIO, true);
398 #endif
399 	gpio_gecko_common_data.count = 0;
400 	IRQ_CONNECT(GPIO_EVEN_IRQn,
401 		    DT_IRQ_BY_NAME(DT_INST(0, silabs_gecko_gpio), gpio_even, priority),
402 		    gpio_gecko_common_isr,
403 		    DEVICE_DT_GET(DT_INST(0, silabs_gecko_gpio)), 0);
404 
405 	IRQ_CONNECT(GPIO_ODD_IRQn,
406 		    DT_IRQ_BY_NAME(DT_INST(0, silabs_gecko_gpio), gpio_odd, priority),
407 		    gpio_gecko_common_isr,
408 		    DEVICE_DT_GET(DT_INST(0, silabs_gecko_gpio)), 0);
409 
410 	irq_enable(GPIO_EVEN_IRQn);
411 	irq_enable(GPIO_ODD_IRQn);
412 
413 	return 0;
414 }
415 
416 #define GPIO_PORT_INIT(idx) \
417 static int gpio_gecko_port##idx##_init(const struct device *dev); \
418 \
419 static const struct gpio_gecko_config gpio_gecko_port##idx##_config = { \
420 	.common = { \
421 		.port_pin_mask = (gpio_port_pins_t)(-1), \
422 	}, \
423 	.gpio_index = GET_GECKO_GPIO_INDEX(idx), \
424 }; \
425 \
426 static struct gpio_gecko_data gpio_gecko_port##idx##_data; \
427 \
428 DEVICE_DT_INST_DEFINE(idx, \
429 		    gpio_gecko_port##idx##_init, \
430 		    NULL, \
431 		    &gpio_gecko_port##idx##_data, \
432 		    &gpio_gecko_port##idx##_config, \
433 		    POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \
434 		    &gpio_gecko_driver_api); \
435 \
436 static int gpio_gecko_port##idx##_init(const struct device *dev) \
437 { \
438 	gpio_gecko_add_port(&gpio_gecko_common_data, dev); \
439 	return 0; \
440 }
441 
442 DT_INST_FOREACH_STATUS_OKAY(GPIO_PORT_INIT)
443