1 /***************************************************************************//**
2  * @file
3  * @brief General Purpose IO (GPIO) peripheral API.
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #include "sl_hal_gpio.h"
32 #if defined(GPIO_PRESENT)
33 #include "sl_hal_bus.h"
34 
35 /*******************************************************************************
36  **************************   GLOBAL FUNCTIONS   *******************************
37  ******************************************************************************/
38 extern __INLINE void sl_hal_gpio_lock(void);
39 extern __INLINE void sl_hal_gpio_unlock(void);
40 extern __INLINE uint32_t sl_hal_gpio_get_lock_status(void);
41 extern __INLINE void sl_hal_gpio_set_pin(const sl_gpio_t *gpio);
42 extern __INLINE void sl_hal_gpio_set_port(sl_gpio_port_t port,
43                                           uint32_t pins);
44 extern __INLINE void sl_hal_gpio_set_port_value(sl_gpio_port_t port,
45                                                 uint32_t val,
46                                                 uint32_t mask);
47 extern __INLINE void sl_hal_gpio_set_slew_rate(sl_gpio_port_t port,
48                                                uint8_t slewrate);
49 extern __INLINE void sl_hal_gpio_set_slew_rate_alternate(sl_gpio_port_t port,
50                                                          uint8_t slewrate_alt);
51 extern __INLINE uint8_t sl_hal_gpio_get_slew_rate(sl_gpio_port_t port);
52 extern __INLINE uint8_t sl_hal_gpio_get_slew_rate_alternate(sl_gpio_port_t port);
53 extern __INLINE void sl_hal_gpio_clear_pin(const sl_gpio_t *gpio);
54 extern __INLINE void sl_hal_gpio_clear_port(sl_gpio_port_t port,
55                                             uint32_t pins);
56 extern __INLINE bool sl_hal_gpio_get_pin_input(const sl_gpio_t *gpio);
57 extern __INLINE bool sl_hal_gpio_get_pin_output(const sl_gpio_t *gpio);
58 extern __INLINE uint32_t sl_hal_gpio_get_port_input(sl_gpio_port_t port);
59 extern __INLINE uint32_t sl_hal_gpio_get_port_output(sl_gpio_port_t port);
60 extern __INLINE void sl_hal_gpio_toggle_pin(const sl_gpio_t *gpio);
61 extern __INLINE void sl_hal_gpio_toggle_port(sl_gpio_port_t port,
62                                              uint32_t pins);
63 extern __INLINE void sl_hal_gpio_enable_interrupts(uint32_t flags);
64 extern __INLINE void sl_hal_gpio_disable_interrupts(uint32_t flags);
65 extern __INLINE void sl_hal_gpio_clear_interrupts(uint32_t flags);
66 extern __INLINE void sl_hal_gpio_set_interrupts(uint32_t flags);
67 extern __INLINE uint32_t sl_hal_gpio_get_pending_interrupts(void);
68 extern __INLINE uint32_t sl_hal_gpio_get_enabled_interrupts(void);
69 extern __INLINE uint32_t sl_hal_gpio_get_enabled_pending_interrupts(void);
70 extern __INLINE int32_t sl_hal_gpio_get_external_interrupt_number(uint8_t pin,
71                                                                   uint32_t enabled_interrupts_mask);
72 extern __INLINE int32_t sl_hal_gpio_get_em4_interrupt_number(const sl_gpio_t *gpio);
73 extern __INLINE void sl_hal_gpio_set_pin_em4_retention(bool enable);
74 extern __INLINE void sl_hal_gpio_disable_pin_em4_wakeup (uint32_t pinmask);
75 extern __INLINE uint32_t sl_hal_gpio_get_pin_em4_wakeup_cause(void);
76 extern __INLINE void sl_hal_gpio_enable_debug_swo(bool enable);
77 extern __INLINE void sl_hal_gpio_enable_debug_swd_clk(bool enable);
78 extern __INLINE void sl_hal_gpio_enable_debug_swd_io(bool enable);
79 
80 /***************************************************************************//**
81  *   Sets the mode for GPIO pin.
82  ******************************************************************************/
sl_hal_gpio_set_pin_mode(const sl_gpio_t * gpio,sl_gpio_mode_t mode,bool output_value)83 void sl_hal_gpio_set_pin_mode(const sl_gpio_t *gpio,
84                               sl_gpio_mode_t mode,
85                               bool output_value)
86 {
87   sl_gpio_mode_t gpio_mode = SL_GPIO_MODE_DISABLED;
88 
89   EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
90   EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
91 
92   switch (mode) {
93 #if defined(_GPIO_P_MODEL_MODE0_DISABLED)
94     case SL_GPIO_MODE_DISABLED:
95       gpio_mode = _GPIO_P_MODEL_MODE0_DISABLED;
96       break;
97 #endif
98 #if defined(_GPIO_P_MODEL_MODE0_INPUT)
99     case SL_GPIO_MODE_INPUT:
100       gpio_mode = _GPIO_P_MODEL_MODE0_INPUT;
101       break;
102 #endif
103 #if defined(_GPIO_P_MODEL_MODE0_INPUTPULL)
104     case SL_GPIO_MODE_INPUT_PULL:
105       gpio_mode = _GPIO_P_MODEL_MODE0_INPUTPULL;
106       break;
107 #endif
108 #if defined(_GPIO_P_MODEL_MODE0_INPUTPULLFILTER)
109     case SL_GPIO_MODE_INPUT_PULL_FILTER:
110       gpio_mode = _GPIO_P_MODEL_MODE0_INPUTPULLFILTER;
111       break;
112 #endif
113 #if defined(_GPIO_P_MODEL_MODE0_PUSHPULL)
114     case SL_GPIO_MODE_PUSH_PULL:
115       gpio_mode = _GPIO_P_MODEL_MODE0_PUSHPULL;
116       break;
117 #endif
118 #if defined(_GPIO_P_MODEL_MODE0_PUSHPULLALT)
119     case SL_GPIO_MODE_PUSH_PULL_ALTERNATE:
120       gpio_mode = _GPIO_P_MODEL_MODE0_PUSHPULLALT;
121       break;
122 #endif
123 #if defined(_GPIO_P_MODEL_MODE0_WIREDOR)
124     case SL_GPIO_MODE_WIRED_OR:
125       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDOR;
126       break;
127 #endif
128 #if defined(_GPIO_P_MODEL_MODE0_WIREDORPULLDOWN)
129     case SL_GPIO_MODE_WIRED_OR_PULL_DOWN:
130       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN;
131       break;
132 #endif
133 #if defined(_GPIO_P_MODEL_MODE0_WIREDAND)
134     case SL_GPIO_MODE_WIRED_AND:
135       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDAND;
136       break;
137 #endif
138 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDFILTER)
139     case SL_GPIO_MODE_WIRED_AND_FILTER:
140       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDFILTER;
141       break;
142 #endif
143 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUP)
144     case SL_GPIO_MODE_WIRED_AND_PULLUP:
145       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDPULLUP;
146       break;
147 #endif
148 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER)
149     case SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER:
150       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER;
151       break;
152 #endif
153 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALT)
154     case SL_GPIO_MODE_WIRED_AND_ALTERNATE:
155       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALT;
156       break;
157 #endif
158 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTFILTER)
159     case SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER:
160       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTFILTER;
161       break;
162 #endif
163 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP)
164     case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP:
165       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP;
166       break;
167 #endif
168 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER)
169     case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER:
170       gpio_mode = _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER;
171       break;
172 #endif
173     default:
174       EFM_ASSERT(false);
175       break;
176   }
177 
178   EFM_ASSERT(SL_HAL_GPIO_MODE_IS_VALID(gpio_mode));
179 
180   // If disabling a pin, do not modify DOUT to reduce the chance of
181   // a glitch/spike (may not be sufficient precaution in all use cases).
182   // As mode settings are dependent on DOUT values, setting output value
183   // prior to mode. @ref enum - sl_gpio_mode_t
184   if (mode != SL_GPIO_MODE_DISABLED) {
185     if (output_value) {
186       sl_hal_gpio_set_pin(gpio);
187     } else {
188       sl_hal_gpio_clear_pin(gpio);
189     }
190   }
191 
192   // There are two registers controlling the pins for each port.
193   // The MODEL register controls pins 0-7 and MODEH controls pins 8-15.
194   if (gpio->pin < 8) {
195     sl_hal_bus_reg_write_mask(&(GPIO->P[gpio->port].MODEL), 0xFu << (gpio->pin * 4), gpio_mode << (gpio->pin * 4));
196   } else {
197     sl_hal_bus_reg_write_mask(&(GPIO->P[gpio->port].MODEH), 0xFu << ((gpio->pin - 8) * 4), gpio_mode << ((gpio->pin - 8) * 4));
198   }
199 
200   // SL_GPIO_MODE_DISABLED based on DOUT Value (low/high) act as two different configurations.
201   // By setting mode to disabled first and then modifying the DOUT value, so that
202   // previous mode configuration on given pin not effected.
203   if (mode == SL_GPIO_MODE_DISABLED) {
204     if (output_value) {
205       sl_hal_gpio_set_pin(gpio);
206     } else {
207       sl_hal_gpio_clear_pin(gpio);
208     }
209   }
210 }
211 
212 /***************************************************************************//**
213  *  Get the mode for a GPIO pin.
214  ******************************************************************************/
sl_hal_gpio_get_pin_mode(const sl_gpio_t * gpio)215 sl_gpio_mode_t sl_hal_gpio_get_pin_mode(const sl_gpio_t *gpio)
216 {
217   sl_gpio_mode_t mode = SL_GPIO_MODE_DISABLED;
218   EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
219 
220   // Determine the current mode of the GPIO pin based on the pin number.
221   if (gpio->pin < 8) {
222     mode = (sl_gpio_mode_t) ((GPIO->P[gpio->port].MODEL >> (gpio->pin * 4)) & 0xF);
223   } else {
224     mode = (sl_gpio_mode_t) ((GPIO->P[gpio->port].MODEH >> ((gpio->pin - 8) * 4)) & 0xF);
225   }
226 
227   // Map the hardware-specific mode to the corresponding sl_gpio_mode_t value
228   switch (mode) {
229 #if defined(_GPIO_P_MODEL_MODE0_DISABLED)
230     case _GPIO_P_MODEL_MODE0_DISABLED:
231       return SL_GPIO_MODE_DISABLED;
232 #endif
233 #if defined(_GPIO_P_MODEL_MODE0_INPUT)
234     case _GPIO_P_MODEL_MODE0_INPUT:
235       return SL_GPIO_MODE_INPUT;
236 #endif
237 #if defined(_GPIO_P_MODEL_MODE0_INPUTPULL)
238     case _GPIO_P_MODEL_MODE0_INPUTPULL:
239       return SL_GPIO_MODE_INPUT_PULL;
240 #endif
241 #if defined(_GPIO_P_MODEL_MODE0_INPUTPULLFILTER)
242     case _GPIO_P_MODEL_MODE0_INPUTPULLFILTER:
243       return SL_GPIO_MODE_INPUT_PULL_FILTER;
244 #endif
245 #if defined(_GPIO_P_MODEL_MODE0_PUSHPULL)
246     case _GPIO_P_MODEL_MODE0_PUSHPULL:
247       return SL_GPIO_MODE_PUSH_PULL;
248 #endif
249 #if defined(_GPIO_P_MODEL_MODE0_PUSHPULLALT)
250     case _GPIO_P_MODEL_MODE0_PUSHPULLALT:
251       return SL_GPIO_MODE_PUSH_PULL_ALTERNATE;
252 #endif
253 #if defined(_GPIO_P_MODEL_MODE0_WIREDOR)
254     case _GPIO_P_MODEL_MODE0_WIREDOR:
255       return SL_GPIO_MODE_WIRED_OR;
256 #endif
257 #if defined(_GPIO_P_MODEL_MODE0_WIREDORPULLDOWN)
258     case _GPIO_P_MODEL_MODE0_WIREDORPULLDOWN:
259       return SL_GPIO_MODE_WIRED_OR_PULL_DOWN;
260 #endif
261 #if defined(_GPIO_P_MODEL_MODE0_WIREDAND)
262     case _GPIO_P_MODEL_MODE0_WIREDAND:
263       return SL_GPIO_MODE_WIRED_AND;
264 #endif
265 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDFILTER)
266     case _GPIO_P_MODEL_MODE0_WIREDANDFILTER:
267       return SL_GPIO_MODE_WIRED_AND_FILTER;
268 #endif
269 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUP)
270     case _GPIO_P_MODEL_MODE0_WIREDANDPULLUP:
271       return SL_GPIO_MODE_WIRED_AND_PULLUP;
272 #endif
273 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER)
274     case _GPIO_P_MODEL_MODE0_WIREDANDPULLUPFILTER:
275       return SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER;
276 #endif
277 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALT)
278     case _GPIO_P_MODEL_MODE0_WIREDANDALT:
279       return SL_GPIO_MODE_WIRED_AND_ALTERNATE;
280 #endif
281 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTFILTER)
282     case _GPIO_P_MODEL_MODE0_WIREDANDALTFILTER:
283       return SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER;
284 #endif
285 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP)
286     case _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUP:
287       return SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP;
288 #endif
289 #if defined(_GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER)
290     case _GPIO_P_MODEL_MODE0_WIREDANDALTPULLUPFILTER:
291       return SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER;
292 #endif
293     default:
294       EFM_ASSERT(false);
295       return mode; // returning the default state
296   }
297 }
298 
299 /***************************************************************************//**
300  *   Configure the GPIO pin interrupt.
301  ******************************************************************************/
sl_hal_gpio_configure_external_interrupt(const sl_gpio_t * gpio,int32_t int_no,sl_gpio_interrupt_flag_t flags)302 int32_t sl_hal_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
303                                                  int32_t int_no,
304                                                  sl_gpio_interrupt_flag_t flags)
305 {
306   EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
307   EFM_ASSERT(SL_GPIO_FLAG_IS_VALID(flags));
308   EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
309 
310   if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE && int_no >= 0) {
311     #if defined(_GPIO_EXTIPINSELL_MASK)
312     EFM_ASSERT(SL_HAL_GPIO_INTNO_PIN_VALID(int_no, gpio->pin));
313     #endif
314   }
315 
316   #if !defined(_GPIO_EXTIPINSELL_MASK)
317   int_no = gpio->pin;
318   #endif
319 
320   if (int_no == SL_GPIO_INTERRUPT_UNAVAILABLE) {
321     uint32_t interrupts_enabled = sl_hal_gpio_get_enabled_interrupts();
322     int_no = sl_hal_gpio_get_external_interrupt_number(gpio->pin, interrupts_enabled);
323   }
324 
325   if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE && int_no >= 0) {
326     if (int_no < 8) {
327       // The EXTIPSELL register controls pins 0-7 of the interrupt configuration.
328       #if defined(_GPIO_EXTIPSELL_EXTIPSEL0_MASK)
329       sl_hal_bus_reg_write_mask(&GPIO->EXTIPSELL,
330                                 _GPIO_EXTIPSELL_EXTIPSEL0_MASK
331                                 << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * int_no),
332                                 (uint32_t)gpio->port << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * int_no));
333       #endif
334       // The EXTIPINSELL register controls interrupt 0-7 of the interrupt/pin number mapping.
335       #if defined(_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK)
336       sl_hal_bus_reg_write_mask(&GPIO->EXTIPINSELL,
337                                 _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK
338                                 << (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * int_no),
339                                 ((gpio->pin % 4) & _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK)
340                                 << (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * int_no));
341       #endif
342     } else {
343       // EXTIPSELH controls pins 8-15 of the interrupt configuration.
344       #if defined(_GPIO_EXTIPSELH_EXTIPSEL0_MASK)
345       uint32_t tmp = int_no - 8;
346       sl_hal_bus_reg_write_mask(&GPIO->EXTIPSELH,
347                                 _GPIO_EXTIPSELH_EXTIPSEL0_MASK
348                                 << (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp),
349                                 (uint32_t)gpio->port << (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp));
350       #endif
351       // EXTIPINSELH controls interrupt 8-15 of the interrupt/pin number mapping.
352       #if defined(_GPIO_EXTIPINSELH_EXTIPINSEL0_MASK)
353       sl_hal_bus_reg_write_mask(&GPIO->EXTIPINSELH,
354                                 _GPIO_EXTIPINSELH_EXTIPINSEL0_MASK
355                                 << (_GPIO_EXTIPINSELH_EXTIPINSEL1_SHIFT * tmp),
356                                 ((gpio->pin % 4) & _GPIO_EXTIPINSELH_EXTIPINSEL0_MASK)
357                                 << (_GPIO_EXTIPSELH_EXTIPSEL1_SHIFT * tmp));
358       #endif
359     }
360 
361     // Enable/disable rising edge interrupt.
362     (((flags & SL_GPIO_INTERRUPT_RISING_EDGE) == SL_GPIO_INTERRUPT_RISING_EDGE)
363      || ((flags & SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) == SL_GPIO_INTERRUPT_RISING_FALLING_EDGE)) \
364     ? sl_hal_bus_reg_write_bit(&(GPIO->EXTIRISE), int_no, true)                                     \
365     : sl_hal_bus_reg_write_bit(&(GPIO->EXTIRISE), int_no, false);
366 
367     // Enable/disable falling edge interrupt.
368     (((flags & SL_GPIO_INTERRUPT_FALLING_EDGE) == SL_GPIO_INTERRUPT_FALLING_EDGE)
369      || (flags & SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) == SL_GPIO_INTERRUPT_RISING_FALLING_EDGE) \
370     ? sl_hal_bus_reg_write_bit(&(GPIO->EXTIFALL), int_no, true)                                   \
371     : sl_hal_bus_reg_write_bit(&(GPIO->EXTIFALL), int_no, false);
372 
373     // Clear any pending interrupt.
374     sl_hal_gpio_clear_interrupts(1 << int_no);
375   }
376 
377   return int_no;
378 }
379 
380 /**************************************************************************//**
381  *   Enable GPIO pin wake-up from EM4. When the function exits,
382  *   EM4 mode can be safely entered.
383  *****************************************************************************/
sl_hal_gpio_enable_pin_em4_wakeup(uint32_t pinmask,uint32_t polaritymask)384 void sl_hal_gpio_enable_pin_em4_wakeup(uint32_t pinmask,
385                                        uint32_t polaritymask)
386 {
387   EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
388   EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
389 
390   GPIO->EM4WUPOL &= ~pinmask;               // Set the wakeup polarity.
391   GPIO->EM4WUPOL |= pinmask & polaritymask;
392   GPIO->EM4WUEN  |= pinmask;                // Enable wakeup.
393 
394   sl_hal_gpio_set_pin_em4_retention(true);  // Enable the pin retention.
395   sl_hal_gpio_clear_interrupts(pinmask);    // clear any pending interrupt.
396 }
397 
398 /***************************************************************************//**
399  *    Configure EM4WU pins as external level-sensitive interrupts.
400  ******************************************************************************/
sl_hal_gpio_configure_wakeup_em4_external_interrupt(const sl_gpio_t * gpio,int32_t int_no,bool polarity)401 int32_t sl_hal_gpio_configure_wakeup_em4_external_interrupt(const sl_gpio_t *gpio,
402                                                             int32_t int_no,
403                                                             bool polarity)
404 {
405   EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
406   EFM_ASSERT(sl_hal_gpio_get_lock_status() == 0);
407 
408   int32_t em4_int_no = sl_hal_gpio_get_em4_interrupt_number(gpio);
409 
410   if (int_no == SL_GPIO_INTERRUPT_UNAVAILABLE) {
411     int_no = em4_int_no;
412   }
413 
414   if (em4_int_no == SL_GPIO_INTERRUPT_UNAVAILABLE || int_no != em4_int_no) {
415     return SL_GPIO_INTERRUPT_UNAVAILABLE;
416   }
417 
418   if (int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
419     // GPIO pin mode set.
420     sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_INPUT_PULL_FILTER, (unsigned int)!polarity);
421 
422     // Enable EM4WU function and set polarity.
423     uint32_t polarityMask = (uint32_t)polarity << (int_no + _GPIO_EM4WUEN_EM4WUEN_SHIFT);
424     uint32_t pinmask =  1UL << (int_no + _GPIO_EM4WUEN_EM4WUEN_SHIFT);
425 
426     sl_hal_gpio_enable_pin_em4_wakeup(pinmask, polarityMask);
427   }
428 
429   return int_no;
430 }
431 
432 #endif /* defined(GPIO_PRESENT)*/
433