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