1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /**
10 * @file gpio_driver.c
11 * @brief The gpio_driver.c file contains Generic API Adaption to SDK 2.0 GPIO Driver.
12 *        The type and variable names have been kept aligned to Kinetis family for compatibility of examples.
13 */
14 
15 #include "gpio_driver.h"
16 
17 /*******************************************************************************
18 * Definitions
19 ******************************************************************************/
20 #define GPIO_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 2) /* driver version */
21 #define GINT_COUNT (sizeof(gintBases) / sizeof(void *))       /* Number of GINTs*/
22 #define GINT_NUMBER_OF_PIN 32                                 /* Each Port has 32 Pins */
23 
24 /*******************************************************************************
25 * Prototypes
26 ******************************************************************************/
27 GINT_Type *const gintBases[] = GINT_BASE_PTRS;
28 #if defined(GINT0)
29 extern void PORT0_IRQHandler(void);
30 #endif
31 #if defined(GINT1)
32 extern void PORT1_IRQHandler(void);
33 #endif
34 #if defined(GINT2)
35 extern void PORT2_IRQHandler(void);
36 #endif
37 #if defined(GINT3)
38 extern void PORT3_IRQHandler(void);
39 #endif
40 #if defined(GINT4)
41 extern void PORT4_IRQHandler(void);
42 #endif
43 #if defined(GINT5)
44 extern void PORT5_IRQHandler(void);
45 #endif
46 #if defined(GINT6)
47 extern void PORT6_IRQHandler(void);
48 #endif
49 #if defined(GINT7)
50 extern void PORT7_IRQHandler(void);
51 #endif
52 
53 /*******************************************************************************
54 * Variables
55 ******************************************************************************/
56 
57 /* Driver Version */
58 static const GENERIC_DRIVER_VERSION DriverVersion = {GPIO_API_VERSION, GPIO_DRV_VERSION};
59 /* ISR handler array for each gpio pin in the system */
60 static gpioIsrObj_t isrObj[GINT_COUNT][GINT_NUMBER_OF_PIN];
61 /* GPIO Pin characteristic */
62 static gpioConfigKSDK_t gpioConfigDefault = {
63     .pinConfig = {kGPIO_DigitalInput, 0}, .interruptMode = kGINT_TrigEdge, .interruptPolarity = kGINT_InterruptLogic_1,
64 };
65 /* GINT base specific ISR callback list */
66 static gint_cb_t gintIsrCb[GINT_COUNT] = {
67 #if defined(GINT0)
68     PORT0_IRQHandler,
69 #endif
70 #if defined(GINT1)
71     PORT1_IRQHandler,
72 #endif
73 #if defined(GINT2)
74     PORT2_IRQHandler,
75 #endif
76 #if defined(GINT3)
77     PORT3_IRQHandler,
78 #endif
79 #if defined(GINT4)
80     PORT4_IRQHandler,
81 #endif
82 #if defined(GINT5)
83     PORT5_IRQHandler,
84 #endif
85 #if defined(GINT6)
86     PORT6_IRQHandler,
87 #endif
88 #if defined(GINT7)
89     PORT7_IRQHandler,
90 #endif
91 };
92 
93 /*******************************************************************************
94  * Code
95  ******************************************************************************/
96 
97 /***********************************************************************
98  *
99  * Function Name : ksdk_gpio_get_version
100  * Description   : get the driver version.
101  *
102  ***************************************************************************/
ksdk_gpio_get_version(void)103 GENERIC_DRIVER_VERSION ksdk_gpio_get_version(void)
104 {
105     return DriverVersion;
106 }
107 
108 /***********************************************************************
109  *
110  * Function Name : ksdk_gpio_pin_init
111  * Description   : Initialize particular GPIO pin used by board.
112  *
113  ***************************************************************************/
ksdk_gpio_pin_init(pinID_t aPinId,gpio_direction_t dir,void * apPinConfig,gpio_isr_handler_t aIsrHandler,void * apUserData)114 void ksdk_gpio_pin_init(
115     pinID_t aPinId, gpio_direction_t dir, void *apPinConfig, gpio_isr_handler_t aIsrHandler, void *apUserData)
116 {
117     uint32_t polarityMask, enableMask;
118 
119     gpioConfigKSDK_t *pGpioConfig;
120     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
121     if (NULL == apPinConfig)
122     {
123         pGpioConfig = &gpioConfigDefault;
124     }
125     else
126     {
127         pGpioConfig = (gpioConfigKSDK_t *)apPinConfig;
128     }
129 
130     // Configure as GPIO
131     CLOCK_EnableClock(pinHandle->clockName);
132     pGpioConfig->pinConfig.pinDirection = (dir == GPIO_DIRECTION_IN) ? kGPIO_DigitalInput : kGPIO_DigitalOutput;
133     GPIO_PinInit(pinHandle->base, pinHandle->portNumber, pinHandle->pinNumber, &pGpioConfig->pinConfig);
134 
135     // Configure is GINT if ISR requested (There should be as many GINTs as there are GPIO Ports).
136     if (aIsrHandler && pinHandle->portNumber < GINT_COUNT)
137     {
138         /* Initialize GINT device for the associated Port */
139         GINT_Init(gintBases[pinHandle->portNumber]);
140 
141         // Enable the IRQ
142         isrObj[pinHandle->portNumber][pinHandle->pinNumber].isrHandle = aIsrHandler;
143         isrObj[pinHandle->portNumber][pinHandle->pinNumber].pUserData = apUserData;
144 
145         /* Setup GINT trigger mode and "OR" mode */
146         GINT_SetCtrl(gintBases[pinHandle->portNumber], kGINT_CombineOr, pGpioConfig->interruptMode,
147                      gintIsrCb[pinHandle->portNumber]);
148 
149         /* Get current pins & polarity for GINT */
150         GINT_GetConfigPins(gintBases[pinHandle->portNumber], pinHandle->portNumber, &polarityMask, &enableMask);
151 
152         /* Update Polarity for this PIN */
153         if (pGpioConfig->interruptPolarity == kGINT_InterruptLogic_1)
154         {
155             polarityMask |= pinHandle->mask; /* Logic 1 for : Level High or Rising Edge  */
156         }
157         else
158         {
159             polarityMask &= ~(pinHandle->mask); /* Logic 0 for : Level Low or Falling Edge */
160         }
161         enableMask |= pinHandle->mask;
162 
163         /* Select pins & polarity for GINT */
164         GINT_ConfigPins(gintBases[pinHandle->portNumber], pinHandle->portNumber, polarityMask, enableMask);
165 
166         /* Enable callbacks for GINT */
167         GINT_EnableCallback(gintBases[pinHandle->portNumber]);
168     }
169 }
170 
171 /***********************************************************************
172  *
173  * Function Name : ksdk_gpio_set_pin
174  * Description   : Set output level of individual GPIO pin to logic 1.
175  *
176  ***************************************************************************/
ksdk_gpio_set_pin(pinID_t aPinId)177 void ksdk_gpio_set_pin(pinID_t aPinId)
178 {
179     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
180     GPIO_PortSet(pinHandle->base, pinHandle->portNumber, pinHandle->mask);
181 }
182 
183 /***********************************************************************
184  *
185  * Function Name : ksdk_gpio_clr_pin
186  * Description   : Set output level of individual GPIO pin to logic 0..
187  *
188  ***************************************************************************/
ksdk_gpio_clr_pin(pinID_t aPinId)189 void ksdk_gpio_clr_pin(pinID_t aPinId)
190 {
191     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
192     GPIO_PortClear(pinHandle->base, pinHandle->portNumber, pinHandle->mask);
193 }
194 
195 /***********************************************************************
196  *
197  * Function Name : ksdk_gpio_toggle_pin
198  * Description   : toggle the currrent output logic of individual GPIO pin.
199  *
200  ***************************************************************************/
ksdk_gpio_toggle_pin(pinID_t aPinId)201 void ksdk_gpio_toggle_pin(pinID_t aPinId)
202 {
203     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
204     GPIO_PortToggle(pinHandle->base, pinHandle->portNumber, pinHandle->mask);
205 }
206 
207 /***********************************************************************
208  *
209  * Function Name : ksdk_gpio_write_pin
210  * Description   : Set output level of individual GPIO pin to desired value, ie 1 or 0.
211  *
212  ***************************************************************************/
ksdk_gpio_write_pin(pinID_t aPinId,uint8_t aValue)213 void ksdk_gpio_write_pin(pinID_t aPinId, uint8_t aValue)
214 {
215     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
216     GPIO_PinWrite(pinHandle->base, pinHandle->portNumber, pinHandle->pinNumber, aValue);
217 }
218 
219 /***********************************************************************
220  *
221  * Function Name : ksdk_gpio_read_pin
222  * Description   : Read current input value of individual GPIO pin.
223  *
224  ***************************************************************************/
ksdk_gpio_read_pin(pinID_t aPinId)225 uint32_t ksdk_gpio_read_pin(pinID_t aPinId)
226 {
227     gpioHandleKSDK_t *pinHandle = (gpioHandleKSDK_t *)aPinId;
228     return GPIO_PinRead(pinHandle->base, pinHandle->portNumber, pinHandle->pinNumber);
229 }
230 
231 /***********************************************************************
232  *
233  * Function Name : ksdk_gpio_handle_interrupt
234  * Description   : handle the gint interrupt of a port.
235  *
236  ***************************************************************************/
issdk_gpio_handle_interrupt(GINT_Type * apBase,gint_port_t aPortNumber)237 void issdk_gpio_handle_interrupt(GINT_Type *apBase, gint_port_t aPortNumber)
238 {
239     uint32_t enableMask, polarityMask;
240 
241     GINT_GetConfigPins(apBase, aPortNumber, &polarityMask, &enableMask);
242     // parse through all the pending interrupt for a PORT
243     for (uint8_t i = 0; i < GINT_NUMBER_OF_PIN; i++)
244     {
245         if (enableMask & (1 << i))
246         {
247             gpio_isr_handler_t handle = isrObj[aPortNumber][i].isrHandle;
248             if (handle == NULL)
249             {
250                 continue;
251             }
252             // call user defined handler
253             handle(isrObj[aPortNumber][i].pUserData);
254         }
255     }
256 }
257 
258 GENERIC_DRIVER_GPIO Driver_GPIO_KSDK = {
259     ksdk_gpio_get_version, ksdk_gpio_pin_init,  ksdk_gpio_set_pin,  ksdk_gpio_clr_pin,
260     ksdk_gpio_toggle_pin,  ksdk_gpio_write_pin, ksdk_gpio_read_pin,
261 };
262