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