1 /***************************************************************************//**
2  * @file
3  * @brief General Purpose IO (GPIO) driver 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 #ifndef SL_GPIO_H
32 #define SL_GPIO_H
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 #include <stdbool.h>
39 #include "sl_status.h"
40 #include "sl_device_gpio.h"
41 
42 #ifndef EM_GPIO_H
43 #define     gpioPortA  0
44 #define     gpioPortB  1
45 #define     gpioPortC  2
46 #define     gpioPortD  3
47 #define     gpioPortE  4
48 #define     gpioPortF  5
49 #define     gpioPortG  6
50 #define     gpioPortH  7
51 #define     gpioPortI  8
52 #define     gpioPortJ  9
53 #define     gpioPortK  10
54 #endif
55 
56 /* *INDENT-OFF* */
57 // *****************************************************************************
58 /// @addtogroup gpio GPIO - General Purpose Input Output
59 /// @brief General Purpose Input Output driver
60 ///
61 /// @li @ref gpio_intro
62 ///
63 ///@n @section gpio_intro Introduction
64 ///  This module contains functions to control the GPIO peripheral of Silicon Labs 32-bit MCUs and SoCs.
65 ///  The GPIO driver is used for external and EM4 interrupt configuration, port and pin configuration.
66 ///  as well as manages the interrupt handler.
67 ///
68 /// @{
69 // *****************************************************************************
70 /* *INDENT-ON* */
71 
72 /*******************************************************************************
73  ********************************   ENUMS   ************************************
74  ******************************************************************************/
75 
76 /// GPIO Pin directions.
SL_ENUM(sl_gpio_pin_direction_t)77 SL_ENUM(sl_gpio_pin_direction_t) {
78   /// Input direction.
79   SL_GPIO_PIN_DIRECTION_IN = 0,
80   /// Output direction.
81   SL_GPIO_PIN_DIRECTION_OUT
82 };
83 
84 /*******************************************************************************
85  *******************************   STRUCTS   ***********************************
86  ******************************************************************************/
87 
88 /***************************************************************************//**
89  * @brief
90  *   Structure for GPIO port and pin configuration.
91  ******************************************************************************/
92 typedef struct {
93   sl_gpio_mode_t mode;
94   sl_gpio_pin_direction_t direction;
95 } sl_gpio_pin_config_t;
96 
97 /*******************************************************************************
98  *******************************   TYPEDEFS   **********************************
99  ******************************************************************************/
100 
101 /***************************************************************************//**
102  * GPIO interrupt callback function pointer.
103  *
104  * @param int_no The pin interrupt number to which the callback function is invoked for.
105  * @param context Pointer to callback context.
106  ******************************************************************************/
107 typedef void (*sl_gpio_irq_callback_t)(uint8_t int_no, void *context);
108 
109 /*******************************************************************************
110  *****************************   PROTOTYPES   **********************************
111  ******************************************************************************/
112 
113 /***************************************************************************//**
114  * Initialization of GPIO driver module.
115  *
116  * @return SL_STATUS_OK if initialization is successful.
117  ******************************************************************************/
118 sl_status_t sl_gpio_init(void);
119 
120 /***************************************************************************//**
121  * Sets the pin direction of GPIO pin.
122  *
123  * @param[in] gpio Pointer to GPIO structure with port and pin
124  * @param[in] pin_dir Pin direction of GPIO pin.
125  *
126  * @return SL_STATUS_OK if there's no error.
127  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin, direction parameters are invalid.
128  *         SL_STATUS_INVALID_STATE if GPIO configuration is in lock state.
129  ******************************************************************************/
130 sl_status_t sl_gpio_set_pin_direction(const sl_gpio_t *gpio,
131                                       sl_gpio_pin_direction_t pin_dir);
132 
133 /***************************************************************************//**
134  * Set the pin mode and set/clear the pin for GPIO pin.
135  *
136  * @param[in] gpio Pointer to GPIO structure with port and pin
137  * @param[in] mode The desired pin mode.
138  * @param[in] output_value Value to set/clear for pin output on the port.
139  *                         Determines the pull-up/pull-down direction of the pin for
140  *                         some input mode configurations.
141  *
142  * @return SL_STATUS_OK if there's no error.
143  *         SL_STATUS_INVALID_PARAMETER if any of the port, pin, mode parameters are invalid.
144  *         SL_STATUS_INVALID_STATE if GPIO configuration is in locked state.
145  ******************************************************************************/
146 sl_status_t sl_gpio_set_pin_mode(const sl_gpio_t *gpio,
147                                  sl_gpio_mode_t mode,
148                                  bool output_value);
149 
150 /***************************************************************************//**
151  * Gets the current configuration selected pin on selected port.
152  *
153  * @param[in] gpio Pointer to GPIO structure with port and pin
154  * @param[out] pin_config Pointer to pin configuration such as mode and direction.
155  *                        Pointer acts as an output and returns the configuration of
156  *                        selected pin on selected port.
157  *
158  * @return SL_STATUS_OK if there's no error.
159  *         SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
160  *         SL_STATUS_NULL_POINTER if pin_config is passed as null.
161  ******************************************************************************/
162 sl_status_t sl_gpio_get_pin_config(const sl_gpio_t *gpio,
163                                    sl_gpio_pin_config_t *pin_config);
164 
165 /***************************************************************************//**
166  * Sets the selected pin of the selected port.
167  *
168  * @param[in] gpio Pointer to GPIO structure with port and pin
169  *
170  * @return SL_STATUS_OK if there's no error.
171  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
172  ******************************************************************************/
173 sl_status_t sl_gpio_set_pin(const sl_gpio_t *gpio);
174 
175 /***************************************************************************//**
176  * Clears the selected pin of the selected port.
177  *
178  * @param[in] gpio Pointer to GPIO structure with port and pin
179  *
180  * @return SL_STATUS_OK if there's no error.
181  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
182  ******************************************************************************/
183 sl_status_t sl_gpio_clear_pin(const sl_gpio_t *gpio);
184 
185 /***************************************************************************//**
186  * Toggles the state of selected pin on selected port.
187  *
188  * @param[in] gpio Pointer to GPIO structure with port and pin
189  *
190  * @return SL_STATUS_OK if there's no error.
191  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
192  ******************************************************************************/
193 sl_status_t sl_gpio_toggle_pin(const sl_gpio_t *gpio);
194 
195 /***************************************************************************//**
196  * Gets the output state of selected pin on selected port.
197  *
198  * @param[in] gpio Pointer to GPIO structure with port and pin
199  * @param[out] pin_value Pointer to return output state of selected pin on selected port
200  *                       when configured to output mode.
201  *
202  * @return SL_STATUS_OK if there's no error.
203  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
204  *         SL_STATUS_NULL_POINTER if pin_value passed as null.
205  ******************************************************************************/
206 sl_status_t sl_gpio_get_pin_output(const sl_gpio_t *gpio,
207                                    bool *pin_value);
208 
209 /***************************************************************************//**
210  * Gets the input state of selected pin on selected port.
211  *
212  * @param[in] gpio Pointer to GPIO structure with port and pin
213  * @param[out] pin_value Pointer to return input state of selected pin on selected port
214  *                       when configured to input mode.
215  *
216  * @return SL_STATUS_OK if there's no error.
217  *         SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
218  *         SL_STATUS_NULL_POINTER if pin_value passed as null.
219  ******************************************************************************/
220 sl_status_t sl_gpio_get_pin_input(const sl_gpio_t *gpio,
221                                   bool *pin_value);
222 
223 /***************************************************************************//**
224  * Sets the selected pin(s) of selected port.
225  *
226  * @param[in] port The GPIO port to access.
227  * @param[in] pins Bit mask for pins to set.
228  *
229  * @return SL_STATUS_OK if there's no error.
230  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
231  ******************************************************************************/
232 sl_status_t sl_gpio_set_port(sl_gpio_port_t port,
233                              uint32_t pins);
234 
235 /***************************************************************************//**
236  * Clears the selected pin(s) of selected port.
237  *
238  * @param[in] port The GPIO Port to access.
239  * @param[in] pins Bit mask for bits to clear.
240  *
241  * @return SL_STATUS_OK if there's no error.
242  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
243  ******************************************************************************/
244 sl_status_t sl_gpio_clear_port(sl_gpio_port_t port,
245                                uint32_t pins);
246 
247 /***************************************************************************//**
248  * Gets the output state of pins of selected port.
249  *
250  * @param[in] gpio The GPIO Port to access.
251  * @param[out] port_value Pointer to return output state of pins on selected port.
252  *
253  * @return SL_STATUS_OK if there's no error.
254  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
255  *         SL_STATUS_NULL_POINTER if port_value passed as null.
256  ******************************************************************************/
257 sl_status_t sl_gpio_get_port_output(sl_gpio_port_t port,
258                                     uint32_t *port_value);
259 
260 /***************************************************************************//**
261  * Gets the input state of pins of selected port.
262  *
263  * @param[in] gpio The GPIO Port to access.
264  * @param[out] port_value Pointer to return output state of pins on selected port.
265  *
266  * @return SL_STATUS_OK if there's no error.
267  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
268  *         SL_STATUS_NULL_POINTER if port_value passed as null.
269  ******************************************************************************/
270 sl_status_t sl_gpio_get_port_input(sl_gpio_port_t port,
271                                    uint32_t *port_value);
272 
273 /***************************************************************************//**
274  * Configures the GPIO pin interrupt.
275  *
276  * @details By default, this function can be used to register a callback which shall be called upon
277  *          interrupt generated for a given pin interrupt number and enables interrupt.
278  *          This function configures and enables the external interrupt and performs
279  *          callback registration.
280  *          It is recommended to use sl_gpio_deconfigure_external_interrupt()
281  *          to disable the interrupt and unregister the callback.
282  *          see @ref sl_gpio_deconfigure_external_interrupt for more information.
283  *          If a valid interrupt number is provided, operation will proceed accordingly.
284  *          Otherwise, a valid interrupt number will be generated based on provided port and
285  *          pin and used for subsequent operations.
286  *
287  * @note If the user has a valid interrupt number to provide as input, it can be used.
288  *       If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
289  *       as value to variable int_no.
290  *       The int_no parameter serves even as an output, a pointer to convey the interrupt number
291  *       for cases where user lacks an interrupt number.
292  * @note the pin number can be selected freely within a group.
293  *       Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
294  *       number within the interrupt groups are:
295  *       0: pins 0-3   (interrupt number 0-3)
296  *       1: pins 4-7   (interrupt number 4-7)
297  *       2: pins 8-11  (interrupt number 8-11)
298  *       3: pins 12-15 (interrupt number 12-15)
299  *
300  * @param[in] gpio Pointer to GPIO structure with port and pin
301  * @param[in/out] int_no Pointer to interrupt number to trigger.
302  *                       Pointer that serves as both an input and an output to return int_no
303  *                       when the user lacks an int_no.
304  * @param[in] flags Interrupt flags for interrupt configuration.
305  *                  Determines the interrupt to get trigger based on rising/falling edge.
306  * @param[in] gpio_callback A pointer to gpio callback function.
307  * @param[in] context A pointer to the callback context.
308  *
309  * @return SL_STATUS_OK if there's no error.
310  *         SL_STATUS_INVALID_PARAMETER if any of the port, pin, flag parameters are invalid.
311  *         SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
312  *         SL_STATUS_NOT_FOUND if there's no available interrupt number.
313  ******************************************************************************/
314 sl_status_t sl_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
315                                                  int32_t *int_no,
316                                                  sl_gpio_interrupt_flag_t flags,
317                                                  sl_gpio_irq_callback_t gpio_callback,
318                                                  void *context);
319 
320 /***************************************************************************//**
321  * Deconfigures the GPIO external pin interrupt.
322  *
323  * @details This function can be used to deconfigure the external GPIO interrupt.
324  *          This function performs callback unregistration, clears and disables the
325  *          given interrupt.
326  *
327  * @note the pin number can be selected freely within a group.
328  *       Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
329  *       number within the interrupt groups are:
330  *       0: pins 0-3   (interrupt number 0-3)
331  *       1: pins 4-7   (interrupt number 4-7)
332  *       2: pins 8-11  (interrupt number 8-11)
333  *       3: pins 12-15 (interrupt number 12-15)
334  *
335  * @param[in] int_no Interrupt number to unregister and disable.
336  *
337  * @return SL_STATUS_OK if there's no error.
338  *         SL_STATUS_INVALID_PARAMETER if int_no is invalid.
339  ******************************************************************************/
340 sl_status_t sl_gpio_deconfigure_external_interrupt(int32_t int_no);
341 
342 /***************************************************************************//**
343  * Enables one or more GPIO Interrupts.
344  *
345  * @param[in] int_mask Mask for GPIO Interrupt sources to enable.
346  *
347  * @return SL_STATUS_OK if there's no error.
348  ******************************************************************************/
349 sl_status_t sl_gpio_enable_interrupts(uint32_t int_mask);
350 
351 /***************************************************************************//**
352  * Disables one or more GPIO Interrupts.
353  *
354  * @param[in] int_mask Mask for GPIO Interrupt sources to disable.
355  *
356  * @return SL_STATUS_OK if there's no error.
357  ******************************************************************************/
358 sl_status_t sl_gpio_disable_interrupts(uint32_t int_mask);
359 
360 /***************************************************************************//**
361  * Configuration EM4WU pins as external level-sensitive interrupts.
362  *
363  * @details By default, this function performs callback registration, enables GPIO pin wake-up from EM4,
364  *          sets the wake-up polarity, enables GPIO pin retention and enables the EM4 wake-up interrupt.
365  *          It is recommended to use sl_gpio_deconfigure_wakeup_em4_interrupt()
366  *          to unregister the callback and disable the em4 interrupt as well as GPIO pin wake-up from EM4.
367  *          It is recommended to use sl_gpio_set_pin_em4_retention() to enable/disable the GPIO pin retention.
368  *          see @ref sl_gpio_deconfigure_wakeup_em4_interrupt() and @ref sl_gpio_set_pin_em4_retention().
369  *          If a valid EM4 wake-up interrupt number is provided, operation will proceed accordingly.
370  *          Otherwise, a valid EM4 interrupt number will be generated based on provided EM4 configured
371  *          port and pin and used for subsequent operations.
372  *
373  * @note If the user has a valid em4 interrupt number to provide as input, it can be used.
374  *       If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
375  *       as value to variable em4_int_no.
376  *       The em4_int_no parameter serves even as an output, a pointer to convey the em4 interrupt number
377  *       for cases where user lacks an em4 interrupt number.
378  * @note There are specific ports and pins mapped to an existent EM4WU interrupt
379  *       Each EM4WU signal is connected to a fixed pin and port.
380  *       Based on chip, EM4 wake up interrupts configured port and pin might vary.
381  *
382  * @param[in] gpio Pointer to GPIO structure with port and pin
383  * @param[in/out] em4_int_no Pointer to interrupt number to trigger.
384  *                           Pointer that serves as both an input and an output to return em4_int_no
385  *                           when the user lacks an em4_int_no.
386  * @param[in] polarity Determines the wakeup polarity.
387  *                     true = Active high level-sensitive interrupt.
388  *                     false = Active low level-sensitive interrupt.
389  * @param[in] gpio_callback A pointer to callback.
390  * @param[in] context A pointer to callback context.
391  *
392  * @return SL_STATUS_OK if there's no error.
393  *         SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
394  *         SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
395  *         SL_STATUS_NOT_FOUND if there's no available interrupt number.
396  ******************************************************************************/
397 sl_status_t sl_gpio_configure_wakeup_em4_interrupt(const sl_gpio_t *gpio,
398                                                    int32_t *em4_int_no,
399                                                    bool polarity,
400                                                    sl_gpio_irq_callback_t gpio_callback,
401                                                    void *context);
402 
403 /***************************************************************************//**
404  * Utilize this function to deconfigure the EM4 GPIO pin interrupt.
405  * It serves to unregister a callback, disable/clear interrupt and clear em4 wakeup source.
406  *
407  * @details This function performs callback unregistration, clears and disables given em4
408  *          interrupt and disables GPIO pin wake-up from EM4.
409  *
410  * @param[in] em4_int_no EM4 wakeup interrupt number.
411  *
412  * @return SL_STATUS_OK if there's no error.
413  *         SL_STATUS_INVALID_PARAMETER if em4_int_no is invalid.
414  ******************************************************************************/
415 sl_status_t sl_gpio_deconfigure_wakeup_em4_interrupt(int32_t em4_int_no);
416 
417 /***************************************************************************//**
418  * Enable EM4 GPIO pin Wake-up bit.
419  * Sets the wakeup and polarity of the EM4 wakeup.
420  *
421  * @param[in] em4_int_mask Mask for setting desired EM4 wake up interrupt to enable.
422  *                         Mask contains the bitwise logic OR of which EM4 wake up interrupt to
423  *                         enable.
424  * @param[in] em4_polarity_mask Mask for setting the wake up polarity for the EM4 wake up interrupt.
425  *                              Mask contains the bitwise logic OR of EM4 wake-up interrupt polarity.
426  *
427  * @return SL_STATUS_OK if there's no error.
428  ******************************************************************************/
429 sl_status_t sl_gpio_enable_pin_em4_wakeup(uint32_t em4_int_mask,
430                                           uint32_t em4_polarity_mask);
431 
432 /***************************************************************************//**
433  * Disabled the GPIO wake up from EM4.
434  *
435  * @param[in] pinmask Mask for clearing desired EM4 wake up interrupt to disable.
436  *                    Mask contains the bitwise logic OR of which EM4 wake up interrupt to
437  *                    disable.
438  *
439  * @return SL_STATUS_OK if there's no error.
440  ******************************************************************************/
441 sl_status_t sl_gpio_disable_pin_em4_wakeup(uint32_t em4_int_mask);
442 
443 /***************************************************************************//**
444  * Enable/Disable GPIO pin retention of output enable, output value, pull enable, and pull direction in EM4.
445  *
446  * @param[in] enable true - enables EM4 pin retention.
447  *                   false - disables EM4 pin retention.
448  *
449  * @return SL_STATUS_OK if there's no error.
450  ******************************************************************************/
451 sl_status_t sl_gpio_set_pin_em4_retention(bool enable);
452 
453 /***************************************************************************//**
454  * Sets slewrate for selected port.
455  *
456  * @param[in] port The GPIO port to configure.
457  * @param[in] slewrate The slewrate to configure the GPIO port.
458  *
459  * @return SL_STATUS_OK if there's no error.
460  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
461  ******************************************************************************/
462 sl_status_t sl_gpio_set_slew_rate(sl_gpio_port_t port,
463                                   uint8_t slewrate);
464 
465 /***************************************************************************//**
466  * Gets slewrate for selected port.
467  *
468  * @param[in] port The GPIO port to get slewrate.
469  * @param[out] slewrate Pointer to store the slewrate of selected port.
470  *
471  * @return SL_STATUS_OK if there's no error.
472  *         SL_STATUS_INVALID_PARAMETER if port is invalid.
473  *         SL_STATUS_NULL_POINTER if slewrate is passed as null.
474  ******************************************************************************/
475 sl_status_t sl_gpio_get_slew_rate(sl_gpio_port_t port,
476                                   uint8_t *slewrate);
477 
478 /***************************************************************************//**
479  * Locks the GPIO Configuration.
480  *
481  * @note This API locks the functionalities such as sl_gpio_set_pin_mode(),
482  *       sl_gpio_configure_external_interrupt() and sl_gpio_configure_wakeup_em4_interrupt().
483  *       After locking the GPIO configuration, use sl_gpio_unlock API to unlock
484  *       the GPIO configuration to use mentioned functionalities.
485  *
486  * @return SL_STATUS_OK if there's no error.
487  ******************************************************************************/
488 sl_status_t sl_gpio_lock(void);
489 
490 /***************************************************************************//**
491  * Unlocks the GPIO Configuration.
492  *
493  * @note After locking the GPIO configuration it is recommended to unlock the GPIO configuration
494  *       using sl_gpio_unlock(). You can determine if the GPIO configuration is locked or unlocked
495  *       by using the sl_gpio_is_locked() function.
496  *       Before using certain functions like sl_gpio_set_pin_mode(),
497  *       sl_gpio_configure_external_interrupt(), and sl_gpio_configure_wakeup_em4_interrupt(),
498  *       it's important to check if the GPIO configuration lock is unlocked.
499  *
500  * @return SL_STATUS_OK if there's no error.
501  ******************************************************************************/
502 sl_status_t sl_gpio_unlock(void);
503 
504 /***************************************************************************//**
505  * Gets current GPIO Lock status.
506  *
507  * @note This function helps check the current status of GPIO configuration.
508  *
509  * @param[out] state Pointer to current state of GPIO configuration (lock/unlock).
510  *
511  * @return SL_STATUS_OK if there's no error.
512  *         SL_STATUS_NULL_POINTER if state is passed as null.
513  ******************************************************************************/
514 sl_status_t sl_gpio_is_locked(bool *state);
515 
516 /** @} (end addtogroup gpio driver) */
517 #ifdef __cplusplus
518 }
519 #endif
520 
521 #endif /* SL_GPIO_H */
522