1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include "hal_base.h"
7 
8 #ifdef HAL_GPIO_MODULE_ENABLED
9 
10 /** @addtogroup RK_HAL_Driver
11  *  @{
12  */
13 
14 /** @addtogroup GPIO
15  *  @{
16  */
17 
18 /** @defgroup GPIO_How_To_Use How To Use
19  *  @{
20 
21  The GPIO driver can be used as follows:
22  APIs for GPIO io read write:
23    1) HAL_GPIO_GetPinLevel to get EXT port level.
24    2) HAL_GPIO_SetPinLevel to set io level.
25    3) HAL_GPIO_SetPinDirection to set io direction.
26 
27  APIs for GPIO IRQ:
28    1) HAL_GPIO_EnableIRQ to enable a GPIO IRQ.
29    2) HAL_GPIO_DisableIRQ to disable a GPIO IRQ.
30    3) HAL_GPIO_IRQHandler to handle GPIO IRQ isr.
31    4) HAL_GPIO_IRQDispatch to dispatch GPIO IRQ, should be implemented by User.
32 
33  @} */
34 
35 /** @defgroup GPIO_Private_Definition Private Definition
36  *  @{
37  */
38 /********************* Private MACRO Definition ******************************/
39 #define UNUSED(X) (void)(X)      /* To avoid gcc/g++ warnings */
40 
41 /********************* Private Function Definition ***************************/
42 
43 /**
44  * @brief  Set the GPIO IRQ end of interrupt(EOI).
45  * @param  pGPIO: The pointer of GPIO struct.
46  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
47  */
GPIO_SetEOI(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)48 static void GPIO_SetEOI(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
49 {
50 #if (GPIO_VER_ID == 0x01000C2BU)
51     if (IS_GPIO_HIGH_PIN(pin)) {
52         pin &= 0xFFFF0000;
53         pGPIO->PORT_EOI_H = pin | (pin >> 16);
54     } else {
55         pin &= 0x0000FFFF;
56         pGPIO->PORT_EOI_L = pin | (pin << 16);
57     }
58 #else
59     {
60         pGPIO->PORTA_EOI = pin;
61     }
62 #endif
63 }
64 
65 /**
66  * @brief  Get GPIO all pins irq type.
67  * @param  pGPIO: the GPIO struct.
68  * @return uint32_t: type value.
69  */
GPIO_GetIntType(struct GPIO_REG * pGPIO)70 static uint32_t GPIO_GetIntType(struct GPIO_REG *pGPIO)
71 {
72     uint32_t type;
73 
74 #if (GPIO_VER_ID == 0x01000C2BU)
75     type = (pGPIO->INT_TYPE_L & 0xffff);
76     type |= ((pGPIO->INT_TYPE_H & 0xffff) << 16);
77     type |= (pGPIO->INT_BOTHEDGE_L & 0xffff);
78     type |= ((pGPIO->INT_BOTHEDGE_H & 0xffff) << 16);
79 #else
80     type = pGPIO->INTTYPE_LEVEL;
81     #ifdef SOC_RK1808
82     type |= pGPIO->INT_BOTHEDGE;
83     #endif
84 #endif
85 
86     return type;
87 }
88 
89 /**
90  * @brief  Get GPIO all pins irq status.
91  * @param  pGPIO: the GPIO struct.
92  * @return uint32_t: status value.
93  */
GPIO_GetIntStatus(struct GPIO_REG * pGPIO)94 static uint32_t GPIO_GetIntStatus(struct GPIO_REG *pGPIO)
95 {
96     return pGPIO->INT_STATUS;
97 }
98 
99 /** @} */
100 /********************* Public Function Definition ***************************/
101 
102 /** @defgroup GPIO_Exported_Functions_Group1 State and Errors Functions
103 
104  This section provides functions allowing to get the status of the module:
105 
106  *  @{
107  */
108 
109 /**
110  * @brief  GPIO Configure IRQ trigger type.
111  * @param  pGPIO: The pointer of GPIO struct.
112  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
113  * @param  mode: The value defined in @ref eGPIO_intType.
114  * @return HAL_Status.
115  */
HAL_GPIO_SetIntType(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin,eGPIO_intType mode)116 HAL_Status HAL_GPIO_SetIntType(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_intType mode)
117 {
118     uint32_t both = 0, type = 0, plar = 0;
119 
120     UNUSED(both);
121 
122     switch (mode) {
123     case GPIO_INT_TYPE_EDGE_RISING:
124         type = 1;
125         plar = 1;
126         both = 0;
127         break;
128     case GPIO_INT_TYPE_EDGE_FALLING:
129         type = 1;
130         plar = 0;
131         both = 0;
132         break;
133     case GPIO_INT_TYPE_LEVEL_HIGH:
134         type = 0;
135         plar = 1;
136         both = 0;
137         break;
138     case GPIO_INT_TYPE_LEVEL_LOW:
139         type = 0;
140         plar = 0;
141         both = 0;
142         break;
143     case GPIO_INT_TYPE_EDGE_BOTH:
144         type = 0;
145         plar = 0;
146         both = 1;
147         break;
148     default:
149 
150         return HAL_INVAL;
151     }
152 
153 #if (GPIO_VER_ID == 0x01000C2BU)
154     if (IS_GPIO_HIGH_PIN(pin)) {
155         pin &= 0xFFFF0000;
156         pGPIO->INT_TYPE_H = (type) ? (pin | (pin >> 16)) : (pin);
157         pGPIO->INT_POLARITY_H = (plar) ? (pin | (pin >> 16)) : (pin);
158         pGPIO->INT_BOTHEDGE_H = (both) ? (pin | (pin >> 16)) : (pin);
159     } else {
160         pin &= 0x0000FFFF;
161         pGPIO->INT_TYPE_L = (type) ? (pin | (pin << 16)) : (pin << 16);
162         pGPIO->INT_POLARITY_L = (plar) ? (pin | (pin << 16)) : (pin << 16);
163         pGPIO->INT_BOTHEDGE_L = (both) ? (pin | (pin << 16)) : (pin << 16);
164     }
165 #else
166     {
167         pGPIO->INTTYPE_LEVEL = (type) ? (pin) : (pGPIO->INTTYPE_LEVEL & ~(pin));
168         pGPIO->INT_POLARITY = (plar) ? (pin) : (pGPIO->INT_POLARITY & ~(pin));
169         #ifdef SOC_RK1808
170         pGPIO->INT_BOTHEDGE = (both) ? (pin) : (pGPIO->INT_BOTHEDGE & ~(pin));
171         #endif
172     }
173 #endif
174 
175     return HAL_OK;
176 }
177 
178 /**
179  * @brief  Set GPIO direction.
180  * @param  pGPIO: the GPIO struct.
181  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
182  * @param  direction: direction value defined in @ref eGPIO_pinDirection.
183  * @return HAL_Status: HAL_OK if success.
184  */
HAL_GPIO_SetPinDirection(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin,eGPIO_pinDirection direction)185 HAL_Status HAL_GPIO_SetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinDirection direction)
186 {
187 #if (GPIO_VER_ID == 0x01000C2BU)
188     if (IS_GPIO_HIGH_PIN(pin)) {
189         pin &= 0xFFFF0000;
190         pGPIO->SWPORT_DDR_H = (direction == GPIO_OUT) ? (pin | (pin >> 16)) : (pin);
191     } else {
192         pin &= 0x0000FFFF;
193         pGPIO->SWPORT_DDR_L = (direction == GPIO_OUT) ? (pin | (pin << 16)) : (pin << 16);
194     }
195 #else
196     {
197         pGPIO->SWPORTA_DDR = (direction == GPIO_OUT) ? (pin) : (pGPIO->SWPORTA_DDR & ~(pin));
198     }
199 #endif
200 
201     return HAL_OK;
202 }
203 
204 /**
205  * @brief  Set GPIO direction.
206  * @param  pGPIO: the GPIO struct.
207  * @param  mPins: The pins defined in @ref ePINCTRL_GPIO_PINS.
208  * @param  direction: value defined in @ref eGPIO_pinDirection.
209  * @return HAL_Status: HAL_OK if success.
210  */
HAL_GPIO_SetPinsDirection(struct GPIO_REG * pGPIO,uint32_t mPins,eGPIO_pinDirection direction)211 HAL_Status HAL_GPIO_SetPinsDirection(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinDirection direction)
212 {
213     uint8_t pin;
214     HAL_Status rc;
215 
216     HAL_ASSERT(IS_GPIO_INSTANCE(pGPIO));
217 
218     for (pin = 0; pin < 32; pin++) {
219         if (mPins & (1 << pin)) {
220             rc = HAL_GPIO_SetPinDirection(pGPIO, (1 << pin), direction);
221             if (rc) {
222                 return rc;
223             }
224         }
225     }
226 
227     return HAL_OK;
228 }
229 
230 /**
231  * @brief  Get GPIO Pin data direction value.
232  * @param  pGPIO: the GPIO struct.
233  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
234  * @retval eGPIO_pinDirection: data direction value.
235  */
HAL_GPIO_GetPinDirection(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)236 eGPIO_pinDirection HAL_GPIO_GetPinDirection(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
237 {
238     eGPIO_pinDirection direction;
239     uint32_t value;
240 
241 #if (GPIO_VER_ID == 0x01000C2BU)
242     value = IS_GPIO_HIGH_PIN(pin) ? (pGPIO->SWPORT_DDR_H & (pin >> 16)) : (pGPIO->SWPORT_DDR_L & pin);
243 #else
244     value = pGPIO->SWPORTA_DDR & pin;
245 #endif
246 
247     if (value != (uint32_t)GPIO_IN) {
248         direction = GPIO_OUT;
249     } else {
250         direction = GPIO_IN;
251     }
252 
253     return direction;
254 }
255 
256 /**
257  * @brief  Set GPIO pin level.
258  * @param  pGPIO: The pointer of GPIO struct.
259  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
260  * @param  level: The level defined in @ref eGPIO_pinLevel.
261  * @return HAL_Status.
262  */
HAL_GPIO_SetPinLevel(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin,eGPIO_pinLevel level)263 HAL_Status HAL_GPIO_SetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin, eGPIO_pinLevel level)
264 {
265 #if (GPIO_VER_ID == 0x01000C2BU)
266     if (IS_GPIO_HIGH_PIN(pin)) {
267         pin &= 0xFFFF0000;
268         pGPIO->SWPORT_DR_H = (level == GPIO_HIGH) ? (pin | (pin >> 16)) : (pin);
269     } else {
270         pin &= 0x0000FFFF;
271         pGPIO->SWPORT_DR_L = (level == GPIO_HIGH) ? (pin | (pin << 16)) : (pin << 16);
272     }
273 #else
274     {
275         pGPIO->SWPORTA_DR = (level == GPIO_HIGH) ? (pin) : (pGPIO->SWPORTA_DR & ~(pin));
276     }
277 #endif
278 
279     return HAL_OK;
280 }
281 
282 /**
283  * @brief  Set GPIO pin level.
284  * @param  pGPIO: The pointer of GPIO struct.
285  * @param  mPins: The pins defined in @ref ePINCTRL_GPIO_PINS.
286  * @param  level: The level defined in @ref eGPIO_pinLevel.
287  * @return HAL_Status.
288  */
HAL_GPIO_SetPinsLevel(struct GPIO_REG * pGPIO,uint32_t mPins,eGPIO_pinLevel level)289 HAL_Status HAL_GPIO_SetPinsLevel(struct GPIO_REG *pGPIO, uint32_t mPins, eGPIO_pinLevel level)
290 {
291     uint8_t pin;
292     HAL_Status rc;
293 
294     HAL_ASSERT(IS_GPIO_INSTANCE(pGPIO));
295 
296     for (pin = 0; pin < 32; pin++) {
297         if (mPins & (1 << pin)) {
298             rc = HAL_GPIO_SetPinLevel(pGPIO, (1 << pin), level);
299             if (rc) {
300                 return rc;
301             }
302         }
303     }
304 
305     return HAL_OK;
306 }
307 
308 /** @} */
309 
310 /** @defgroup GPIO_Exported_Functions_Group2 IO Functions
311 
312  This section provides functions allowing to IO controlling:
313 
314  *  @{
315  */
316 
317 /**
318  * @brief  Get GPIO Pin data value.
319  * @param  pGPIO: the GPIO struct.
320  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
321  * @retval eGPIO_pinLevel: data value.
322  */
HAL_GPIO_GetPinData(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)323 eGPIO_pinLevel HAL_GPIO_GetPinData(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
324 {
325     eGPIO_pinLevel level;
326     uint32_t value;
327 
328 #if (GPIO_VER_ID == 0x01000C2BU)
329     value = IS_GPIO_HIGH_PIN(pin) ? (pGPIO->SWPORT_DR_H & (pin >> 16)) : (pGPIO->SWPORT_DR_L & pin);
330 #else
331     value = pGPIO->SWPORTA_DR & pin;
332 #endif
333 
334     if (value != (uint32_t)GPIO_LOW) {
335         level = GPIO_HIGH;
336     } else {
337         level = GPIO_LOW;
338     }
339 
340     return level;
341 }
342 
343 /**
344  * @brief  Get GPIO Pin ext bank level.
345  * @param  pGPIO: the GPIO struct.
346  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
347  * @retval GPIO_PinState: ext bank value.
348  */
HAL_GPIO_GetPinLevel(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)349 eGPIO_pinLevel HAL_GPIO_GetPinLevel(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
350 {
351     uint32_t value;
352 
353 #if (GPIO_VER_ID == 0x01000C2BU)
354     value = (pGPIO->EXT_PORT & pin);
355 #else
356     value = (pGPIO->EXT_PORTA & pin);
357 #endif
358 
359     return (value == (uint32_t)GPIO_LOW) ? GPIO_LOW : GPIO_HIGH;
360 }
361 
362 /**
363  * @brief  Get GPIO Pin ext bank level.
364  * @param  pGPIO: the GPIO struct.
365  * @retval uint32_t: ext bank value.
366  */
HAL_GPIO_GetBankLevel(struct GPIO_REG * pGPIO)367 uint32_t HAL_GPIO_GetBankLevel(struct GPIO_REG *pGPIO)
368 {
369     uint32_t value;
370 
371 #if (GPIO_VER_ID == 0x01000C2BU)
372     value = (pGPIO->EXT_PORT);
373 #else
374     value = (pGPIO->EXT_PORTA);
375 #endif
376 
377     return value;
378 }
379 /** @} */
380 
381 /** @defgroup GPIO_Exported_Functions_Group3 Other Functions
382  *  @{
383  */
384 
385 /**
386  * @brief  Set GPIO irq enable.
387  * @param  pGPIO: The pointer of GPIO struct.
388  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
389  */
HAL_GPIO_EnableIRQ(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)390 void HAL_GPIO_EnableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
391 {
392 #if (GPIO_VER_ID == 0x01000C2BU)
393     if (IS_GPIO_HIGH_PIN(pin)) {
394         pin &= 0xFFFF0000;
395 #ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
396         pGPIO->INT_MASK_H = pin;
397 #endif
398         pGPIO->INT_EN_H = pin | (pin >> 16);
399     } else {
400         pin &= 0x0000FFFF;
401 #ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
402         pGPIO->INT_MASK_L = pin << 16;
403 #endif
404         pGPIO->INT_EN_L = pin | (pin << 16);
405     }
406 #else
407     {
408         pGPIO->INTEN |= pin;
409         pGPIO->INTMASK &= ~pin;
410     }
411 #endif
412 }
413 
414 /**
415  * @brief  Set GPIO irq disable.
416  * @param  pGPIO: The pointer of GPIO struct.
417  * @param  pin: The pin bit defined in @ref ePINCTRL_GPIO_PINS.
418  */
HAL_GPIO_DisableIRQ(struct GPIO_REG * pGPIO,ePINCTRL_GPIO_PINS pin)419 void HAL_GPIO_DisableIRQ(struct GPIO_REG *pGPIO, ePINCTRL_GPIO_PINS pin)
420 {
421 #if (GPIO_VER_ID == 0x01000C2BU)
422     if (IS_GPIO_HIGH_PIN(pin)) {
423         pin &= 0xFFFF0000;
424         pGPIO->INT_EN_H = pin;
425 #ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
426         pGPIO->INT_MASK_H = pin | (pin >> 16);
427 #endif
428     } else {
429         pin &= 0x0000FFFF;
430         pGPIO->INT_EN_L = pin << 16;
431 #ifndef HAL_GPIO_IRQ_GROUP_MODULE_ENABLED
432         pGPIO->INT_MASK_L = pin | (pin << 16);
433 #endif
434     }
435 #else
436     {
437         pGPIO->INTEN &= ~pin;
438         pGPIO->INTMASK |= pin;
439     }
440 #endif
441 }
442 
443 /**
444  * @brief  GPIO IRQ callbacks.
445  * @param  bank: The bank id.
446  * @param  pin: The true pin index, 0~31.
447  * NOTE: This function Should not be modified, when the callback is needed,
448  *       the HAL_GPIO_IRQDispatch could be implemented in the user file.
449  */
HAL_GPIO_IRQDispatch(eGPIO_bankId bank,uint32_t pin)450 __WEAK void HAL_GPIO_IRQDispatch(eGPIO_bankId bank, uint32_t pin)
451 {
452     UNUSED(bank);
453     UNUSED(pin);
454 }
455 
456 /**
457  * @brief  GPIO IRQ hanlder.
458  * @param  pGPIO: The pointer of GPIO struct.
459  * @param  bank: The bank id.
460  */
HAL_GPIO_IRQHandler(struct GPIO_REG * pGPIO,eGPIO_bankId bank)461 void HAL_GPIO_IRQHandler(struct GPIO_REG *pGPIO, eGPIO_bankId bank)
462 {
463     uint32_t stat, type, clear;
464     uint32_t i;
465     uint32_t pin;
466 
467     stat = GPIO_GetIntStatus(pGPIO);
468     type = GPIO_GetIntType(pGPIO);
469 
470     /* Then process each pending GPIO interrupt */
471     for (i = 0x0U; i < PIN_NUMBER_PER_BANK && stat != 0; i++) {
472         clear = 0x1U << i;
473         pin = HAL_BIT(i);
474 
475         if ((stat & clear) != 0x0U) {
476             /* If gpio is Edge-sensitive triggered, clear eoi */
477             if (type & clear) {
478                 GPIO_SetEOI(pGPIO, pin);
479             }
480 
481             /* Remove the pending interrupt bit from the clear */
482             stat &= ~clear;
483 
484             /* And disptach the GPIO interrupt to the handler */
485             HAL_GPIO_IRQDispatch(bank, i);
486         }
487     }
488 }
489 /** @} */
490 
491 /** @} */
492 
493 /** @} */
494 
495 #endif /* HAL_GPIO_MODULE_ENABLED */
496