• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /******************************************************************************
17  * @file     dw_gpio.c
18  * @brief    CSI Source File for GPIO Driver
19  * @version  V1.0
20  * @date     02. June 2017
21  ******************************************************************************/
22 
23 #include <csi_config.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include "drv_gpio.h"
27 #include "drv_pmu.h"
28 #include "dw_gpio.h"
29 #include "csi_core.h"
30 #include "pin_name.h"
31 #if defined CONFIG_CHIP_ERAGON3 || defined CONFIG_CHIP_SMARTH_MMU || defined CONFIG_CHIP_SMARTH_610 || defined CONFIG_CHIP_SMARTH_610M
32 #include <drv_intc.h>
33 #endif
34 
35 extern int32_t drv_pin_config_mode(port_name_e port, uint8_t offset, gpio_mode_e pin_mode);
36 
37 #define ERR_GPIO(errno) (CSI_DRV_ERRNO_GPIO_BASE | errno)
38 #define GPIO_NULL_PARAM_CHK(para)    HANDLE_PARAM_CHK(para, ERR_GPIO(DRV_ERROR_PARAMETER))
39 
40 typedef void *gpio_port_handle_t;
41 
42 typedef struct {
43 #ifdef CONFIG_LPM
44     uint8_t gpio_power_status;
45     uint32_t gpio_regs_saved[7];
46 #endif
47     uint32_t base;              ///< handle register base
48     uint32_t irq;               ///< irq of this handle
49     uint32_t pin_num;           ///< pin number of this handle
50     gpio_mode_e mode;           ///< gpio mode
51     gpio_direction_e dir;       ///< gpio direction
52     uint32_t mask;              ///< gpio mask bit
53     uint32_t value;             ///< gpio value
54 } dw_gpio_priv_t;
55 
56 typedef struct {
57     uint8_t     portidx;
58     uint8_t     idx;
59     gpio_event_cb_t cb;
60 } dw_gpio_pin_priv_t;
61 
62 extern int32_t target_gpio_port_init(port_name_e port, uint32_t *base, uint32_t *irq, uint32_t *pin_num);
63 extern int32_t target_gpio_pin_init(int32_t gpio_pin, uint32_t *port_idx);
64 
65 static dw_gpio_priv_t gpio_handle[CONFIG_GPIO_NUM];
66 static dw_gpio_pin_priv_t gpio_pin_handle[CONFIG_GPIO_PIN_NUM];
67 
68 //
69 // Functions
70 //
gpio_set_direction(void * port,gpio_direction_e direction)71 static int32_t gpio_set_direction(
72     void *port,
73     gpio_direction_e direction
74 )
75 {
76     dw_gpio_priv_t *gpio_priv = port;
77     dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base);
78 
79     if (direction == GPIO_DIRECTION_INPUT) {
80         gpio_reg->SWPORT_DDR &= (~gpio_priv->mask);
81     } else if (direction == GPIO_DIRECTION_OUTPUT) {
82         gpio_reg->SWPORT_DDR |= gpio_priv->mask;
83     } else {
84         return ERR_GPIO(GPIO_ERROR_DIRECTION);
85     }
86 
87     return 0;
88 }
89 
90 /*
91  * Read the statu of the Port choosed.
92  * Parameters:
93  *   port:  use to choose a I/O port among Port A, B, or C.
94  * return: the value of the corresponding Port.
95  */
96 
gpio_read(void * port,uint32_t * value)97 static int32_t gpio_read(void *port, uint32_t *value)
98 {
99     dw_gpio_priv_t *gpio_priv = port;
100     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_priv->base + 0x30);
101     *value = gpio_control_reg->EXT_PORTA;
102     return 0;
103 }
104 
105 
106 /*
107  * Write an output value to corresponding Port.
108  * Parameters:
109  *   port:  use to choose a I/O port among Port A, B, or C.
110  *   output: value that will be written to the corresponding Port.
111  * return: SUCCESS
112  */
113 
gpio_write(void * port,uint32_t mask)114 static int32_t gpio_write(void *port, uint32_t mask)
115 {
116     dw_gpio_priv_t *gpio_priv = port;
117     dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base);
118 
119     uint32_t value = gpio_reg->SWPORT_DR;
120 
121     value &= ~(mask);
122     value |= gpio_priv->value;
123     gpio_reg->SWPORT_DR = value;
124     return 0;
125 }
126 
127 /**
128  * Configure a GPIO gpio_set_irq_mode.
129  * @param[in]   pin         the addr store the pin num.
130  * @param[in]   _irqmode    the irqmode of gpio
131  * @return      zero on success. -1 on falure.
132  */
gpio_set_irq_mode(gpio_pin_handle_t pin,gpio_irq_mode_e irq_mode)133 static int32_t gpio_set_irq_mode(gpio_pin_handle_t pin, gpio_irq_mode_e irq_mode)
134 {
135     dw_gpio_pin_priv_t *gpio_pin_priv = pin;
136 
137     /* convert portidx to port handle */
138     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
139 
140     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
141     uint32_t offset = gpio_pin_priv->idx;
142     uint32_t mask = 1 << offset;
143 
144     switch (irq_mode) {
145         /* rising edge interrupt mode */
146         case GPIO_IRQ_MODE_RISING_EDGE:
147             gpio_control_reg->INTTYPE_LEVEL |= mask;
148             gpio_control_reg->INT_POLARITY |= mask;
149             break;
150 
151         /* falling edge interrupt mode */
152         case GPIO_IRQ_MODE_FALLING_EDGE:
153             gpio_control_reg->INTTYPE_LEVEL |= mask;
154             gpio_control_reg->INT_POLARITY &= (~mask);
155             break;
156 
157         /* low level interrupt mode */
158         case GPIO_IRQ_MODE_LOW_LEVEL:
159             gpio_control_reg->INTTYPE_LEVEL &= (~mask);
160             gpio_control_reg->INT_POLARITY &= (~mask);
161             break;
162 
163         /* high level interrupt mode */
164         case GPIO_IRQ_MODE_HIGH_LEVEL:
165             gpio_control_reg->INTTYPE_LEVEL &= (~mask);
166             gpio_control_reg->INT_POLARITY |= mask;
167             break;
168 
169         /* double edge interrupt mode */
170         case GPIO_IRQ_MODE_DOUBLE_EDGE:
171             return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
172 
173         default:
174             return ERR_GPIO(GPIO_ERROR_IRQ_MODE);
175     }
176 
177     return 0;
178 }
179 
180 /*
181  * Clear one or more interrupts of PortA.
182  * Parameters:
183  *   pinno:
184  * return: SUCCESS.
185  */
186 
gpio_irq_clear(gpio_pin_handle_t pin,uint32_t idx)187 static void gpio_irq_clear(gpio_pin_handle_t pin, uint32_t idx)
188 {
189     dw_gpio_pin_priv_t *gpio_pin_priv = pin;
190 
191     /* convert portidx to port handle */
192     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
193 
194     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
195 
196     gpio_control_reg->PORTA_EOI = idx;
197 }
198 
199 
200 /*
201  * Enable one or more interrupts of PortA.
202  * Parameters:
203  *   pinno:
204  * return: SUCCESS.
205  */
gpio_irq_enable(gpio_pin_handle_t pin)206 static void gpio_irq_enable(gpio_pin_handle_t pin)
207 {
208     dw_gpio_pin_priv_t *gpio_pin_priv = pin;
209 
210     /* convert portidx to port handle */
211     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
212 
213     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
214     uint32_t offset = gpio_pin_priv->idx;
215     uint32_t val = gpio_control_reg->INTEN;
216     val |= (1 << offset);
217     gpio_control_reg->INTEN = val;
218 }
219 
220 
221 /*
222  * Disable one or more interrupts of PortA.
223  * Parameters:
224  *   pinno:
225  * return: SUCCESS.
226  */
227 
gpio_irq_disable(gpio_pin_handle_t pin)228 static void gpio_irq_disable(gpio_pin_handle_t pin)
229 {
230     dw_gpio_pin_priv_t *gpio_pin_priv = pin;
231     uint32_t offset = gpio_pin_priv->idx;
232 
233     /* convert portidx to port handle */
234     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
235 
236     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
237     uint32_t val = gpio_control_reg->INTEN;
238     val &= ~(1 << offset);
239     gpio_control_reg->INTEN = val;
240 }
241 
dw_gpio_irqhandler(int idx)242 void dw_gpio_irqhandler(int idx)
243 {
244     if (idx >= CONFIG_GPIO_NUM) {
245         return;
246     }
247 
248     dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_handle[idx].base + 0x30);
249 
250     uint32_t value = gpio_control_reg->INTSTATUS;
251     uint8_t i;
252 
253     /* find the interrput pin */
254     for (i = 0; i < 32; i++) {
255         if (value & (1U << i)) {
256             uint32_t pin_idx = i;
257 
258 #ifndef CONFIG_CHIP_DANICA
259             uint8_t j;
260 
261             if (idx > 0) {
262                 for (j = 0; j < idx; j++) {
263                     pin_idx += gpio_handle[j].pin_num;
264                 }
265             }
266 
267             if (pin_idx >= CONFIG_GPIO_PIN_NUM) {
268                 return;
269             }
270 
271 #endif
272             dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)&gpio_pin_handle[pin_idx];
273 
274             gpio_irq_clear(gpio_pin_priv, (1 << i));  //clear the gpio interrupt
275 
276             /* execute the callback function */
277             if ((gpio_event_cb_t)(gpio_pin_priv->cb)) {
278                 ((gpio_event_cb_t)(gpio_pin_priv->cb))(pin_idx);
279             }
280         }
281     }
282 }
283 
284 /**
285   \brief       Initialize GPIO module. 1. Initializes the resources needed for the GPIO handle 2.registers event callback function
286                 3.get gpio_port_handle
287   \param[in]   port      port_name.
288   \return      gpio_port_handle
289 */
csi_gpio_port_initialize(int32_t port)290 gpio_port_handle_t csi_gpio_port_initialize(int32_t port)
291 {
292     dw_gpio_priv_t *gpio_priv = NULL;
293 
294     /* obtain the gpio port information */
295     uint32_t base = 0u;
296     uint32_t pin_num;
297     uint32_t irq;
298     int32_t idx = target_gpio_port_init(port, &base, &irq, &pin_num);
299 
300     if (idx < 0 || idx >= CONFIG_GPIO_NUM) {
301         return NULL;
302     }
303 
304     gpio_priv = &gpio_handle[idx];
305 
306     gpio_priv->base = base;
307     gpio_priv->irq  = irq;
308     gpio_priv->pin_num  = pin_num;
309 
310 #ifdef CONFIG_LPM
311     csi_gpio_power_control(gpio_priv, DRV_POWER_FULL);
312 #endif
313 
314 #if defined CONFIG_CHIP_ERAGON3 || defined CONFIG_CHIP_SMARTH_MMU || defined CONFIG_CHIP_SMARTH_610 || defined CONFIG_CHIP_SMARTH_610M
315     csi_intc_enable_irq(gpio_priv->irq);
316 #else
317     csi_vic_enable_irq(gpio_priv->irq);
318 #endif
319 
320     return (gpio_port_handle_t)gpio_priv;
321 }
322 
323 /**
324   \brief       De-initialize GPIO handle. stops operation and releases the software resources used by the handle
325   \param[in]   handle   gpio port handle to operate.
326   \return      error code
327 */
csi_gpio_port_uninitialize(gpio_port_handle_t handle)328 int32_t csi_gpio_port_uninitialize(gpio_port_handle_t handle)
329 {
330     GPIO_NULL_PARAM_CHK(handle);
331 
332     dw_gpio_priv_t *gpio_priv = handle;
333 
334 #if defined CONFIG_CHIP_ERAGON3 || defined CONFIG_CHIP_SMARTH_MMU || defined CONFIG_CHIP_SMARTH_610 || defined CONFIG_CHIP_SMARTH_610M
335     csi_intc_disable_irq(gpio_priv->irq);
336 #else
337     csi_vic_disable_irq(gpio_priv->irq);
338 #endif
339 #ifdef CONFIG_LPM
340     csi_gpio_power_control(gpio_priv, DRV_POWER_OFF);
341 #endif
342 
343     return 0;
344 }
345 
346 /**
347   \brief       config multiple pin within one handle
348   \param[in]   handle    gpio port handle to operate.
349   \param[in]   mask      the bitmask to identify which bits in the handle should be included (0 - ignore)
350   \param[in]   mode      \ref gpio_mode_e
351   \param[in]   dir       \ref gpio_direction_e
352   \return      error code
353 */
csi_gpio_port_config(gpio_port_handle_t handle,uint32_t mask,gpio_mode_e mode,gpio_direction_e dir)354 int32_t csi_gpio_port_config(gpio_port_handle_t handle, uint32_t mask, gpio_mode_e mode, gpio_direction_e dir)
355 {
356     GPIO_NULL_PARAM_CHK(handle);
357 
358     dw_gpio_priv_t *gpio_priv = handle;
359 
360     /*config the gpio mode direction mask bits */
361     switch (mode) {
362         case GPIO_MODE_PULLNONE:
363             gpio_priv->mode = mode;
364             break;
365 
366         case GPIO_MODE_PULLUP:
367         case GPIO_MODE_PULLDOWN:
368         case GPIO_MODE_OPEN_DRAIN:
369         case GPIO_MODE_PUSH_PULL:
370             return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
371 
372         default:
373             return ERR_GPIO(GPIO_ERROR_MODE);
374     }
375 
376     gpio_priv->dir = dir;
377     gpio_priv->mask = mask;
378     uint32_t ret = gpio_set_direction(gpio_priv, dir);
379 
380     return ret;
381 }
382 
383 /**
384   \brief       Write value to the handle(write value to multiple pins on one handle at the same time)
385   \param[in]   handle    gpio port handle to operate.
386   \param[in]   mask      The bitmask to identify which bits in the handle should be included (0 - ignore)
387   \param[in]   value     the value to be set
388   \return      error code
389 */
csi_gpio_port_write(gpio_port_handle_t handle,uint32_t mask,uint32_t value)390 int32_t csi_gpio_port_write(gpio_port_handle_t handle, uint32_t mask, uint32_t value)
391 {
392     GPIO_NULL_PARAM_CHK(handle);
393 
394     uint32_t port_value = mask & value;
395 
396     dw_gpio_priv_t *gpio_priv = handle;
397     gpio_priv->value = port_value;
398     gpio_write(gpio_priv, mask);
399 
400     return 0;
401 
402 }
403 
404 /**
405   \brief       Read the current value on the handle(read value of multiple pins on one handle at the same time)
406   \param[in]   handle    gpio port handle to operate.
407   \param[in]   mask      The bitmask to identify which bits in the handle should be included (0 - ignore)
408   \param[out]  value     an integer with each bit corresponding to an associated handle pin setting
409   \return      error code
410 */
csi_gpio_port_read(gpio_port_handle_t handle,uint32_t mask,uint32_t * value)411 int32_t csi_gpio_port_read(gpio_port_handle_t handle, uint32_t mask, uint32_t *value)
412 {
413     GPIO_NULL_PARAM_CHK(handle);
414     GPIO_NULL_PARAM_CHK(value);
415 
416     uint32_t port_value = 0;
417 
418     gpio_read(handle, &port_value);
419     *value = (mask & port_value);
420 
421     return 0;
422 
423 }
424 
425 #ifdef CONFIG_LPM
manage_clock(gpio_pin_handle_t handle,uint8_t enable)426 static void manage_clock(gpio_pin_handle_t handle, uint8_t enable)
427 {
428     dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle;
429     uint8_t device[] = {CLOCK_MANAGER_GPIO0, CLOCK_MANAGER_GPIO1};
430 
431     drv_clock_manager_config(device[gpio_pin_priv->portidx], enable);
432 }
433 
do_prepare_sleep_action(void * handle)434 static void do_prepare_sleep_action(void *handle)
435 {
436     dw_gpio_priv_t *gpio_handle = handle;
437     uint32_t *gbase = (uint32_t *)(gpio_handle->base);
438     uint32_t *control_base = (uint32_t *)(gpio_handle->base + 0x30);
439     registers_save(gpio_handle->gpio_regs_saved, gbase, 3);
440     registers_save(&gpio_handle->gpio_regs_saved[3], control_base, 4);
441 }
442 
do_wakeup_sleep_action(void * handle)443 static void do_wakeup_sleep_action(void *handle)
444 {
445     dw_gpio_priv_t *gpio_handle = handle;
446     uint32_t *gbase = (uint32_t *)(gpio_handle->base);
447     uint32_t *control_base = (uint32_t *)(gpio_handle->base + 0x30);
448     registers_restore(gbase, gpio_handle->gpio_regs_saved, 3);
449     registers_restore(control_base, &gpio_handle->gpio_regs_saved[3], 4);
450 }
451 #endif
452 
453 /**
454   \brief       Initialize GPIO handle.
455   \param[in]   gpio_pin    Pointer to the int32_t.
456   \param[in]   cb_event    Pointer to \ref gpio_event_cb_t.
457   \param[in]   arg    Pointer to \ref arg used for the callback.
458   \return      gpio_pin_handle
459 */
csi_gpio_pin_initialize(int32_t gpio_pin,gpio_event_cb_t cb_event)460 gpio_pin_handle_t csi_gpio_pin_initialize(int32_t gpio_pin, gpio_event_cb_t cb_event)
461 {
462 
463     if (gpio_pin < 0 || gpio_pin >= CONFIG_GPIO_PIN_NUM) {
464         return NULL;
465     }
466 
467     uint32_t i;
468 
469     for (i = 0; i < CONFIG_GPIO_NUM; i++) {
470         csi_gpio_port_initialize(i);
471     }
472 
473     /* obtain the gpio pin information */
474     uint32_t port_idx;
475     int32_t pin_idx = target_gpio_pin_init(gpio_pin, &port_idx);
476 
477     if (pin_idx < 0) {
478         return NULL;
479     }
480 
481     int32_t idx = pin_idx;
482 
483     for (i = 0; i < port_idx; i++) {
484         idx += (gpio_handle[i].pin_num);
485     }
486 
487     dw_gpio_pin_priv_t *gpio_pin_priv = &(gpio_pin_handle[idx]);
488     gpio_pin_priv->portidx = port_idx;
489 
490 
491     gpio_pin_priv->idx = pin_idx;
492     gpio_pin_priv->cb = cb_event;
493 
494     return (gpio_pin_handle_t)gpio_pin_priv;
495 }
496 
497 /**
498   \brief       De-initialize GPIO pin handle. stops operation and releases the software resources used by the handle
499   \param[in]   handle   gpio pin handle to operate.
500   \return      error code
501 */
csi_gpio_pin_uninitialize(gpio_pin_handle_t handle)502 int32_t csi_gpio_pin_uninitialize(gpio_pin_handle_t handle)
503 {
504     if (handle == NULL) {
505         return ERR_GPIO(DRV_ERROR_PARAMETER);
506     }
507 
508     dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle;
509     gpio_pin_priv->cb = NULL;
510 
511     gpio_irq_disable(handle);
512 
513     return 0;
514 }
515 
516 /**
517   \brief       control gpio power.
518   \param[in]   idx  gpio index.
519   \param[in]   state   power state.\ref csi_power_stat_e.
520   \return      error code
521 */
csi_gpio_power_control(gpio_pin_handle_t handle,csi_power_stat_e state)522 int32_t csi_gpio_power_control(gpio_pin_handle_t handle, csi_power_stat_e state)
523 {
524     GPIO_NULL_PARAM_CHK(handle);
525 
526 #ifdef CONFIG_LPM
527     dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle;
528     power_cb_t callback = {
529         .wakeup = do_wakeup_sleep_action,
530         .sleep = do_prepare_sleep_action,
531         .manage_clock = manage_clock
532     };
533     return drv_soc_power_control(&gpio_handle[gpio_pin_priv->portidx], state, &callback);
534 #else
535     return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
536 #endif
537 }
538 
539 /**
540   \brief       config pin mode
541   \param[in]   pin       gpio pin handle to operate.
542   \param[in]   mode      \ref gpio_mode_e
543   \return      error code
544 */
csi_gpio_pin_config_mode(gpio_pin_handle_t handle,gpio_mode_e mode)545 int32_t csi_gpio_pin_config_mode(gpio_pin_handle_t handle,
546                                  gpio_mode_e mode)
547 {
548     GPIO_NULL_PARAM_CHK(handle);
549 
550     /* config the gpio pin mode direction mask bits */
551     dw_gpio_pin_priv_t *gpio_pin_priv = handle;
552 
553     uint8_t offset = gpio_pin_priv->idx;
554 
555     int32_t ret = drv_pin_config_mode(gpio_pin_priv->portidx, offset, mode);
556 
557     return ret;
558 }
559 /**
560   \brief       config pin direction
561   \param[in]   pin       gpio pin handle to operate.
562   \param[in]   dir       \ref gpio_direction_e
563   \return      error code
564 */
csi_gpio_pin_config_direction(gpio_pin_handle_t handle,gpio_direction_e dir)565 int32_t csi_gpio_pin_config_direction(gpio_pin_handle_t handle,
566                                       gpio_direction_e dir)
567 {
568     GPIO_NULL_PARAM_CHK(handle);
569 
570     /* config the gpio pin mode direction mask bits */
571     dw_gpio_pin_priv_t *gpio_pin_priv = handle;
572 
573     /* convert portidx to port handle */
574     dw_gpio_priv_t *gpio_priv = &gpio_handle[gpio_pin_priv->portidx];
575 
576     gpio_priv->dir = dir;
577     gpio_priv->mask = 1 << gpio_pin_priv->idx;
578 
579     uint32_t ret = gpio_set_direction(gpio_priv, dir);
580 
581     if (ret) {
582         return ret;
583     }
584 
585     return 0;
586 }
587 
588 /**
589   \brief       config pin
590   \param[in]   handle       gpio pin handle to operate.
591   \param[in]   mode      \ref gpio_mode_e
592   \param[in]   dir       \ref gpio_direction_e
593   \return      error code
594 */
csi_gpio_pin_config(gpio_pin_handle_t handle,gpio_mode_e mode,gpio_direction_e dir)595 int32_t csi_gpio_pin_config(gpio_pin_handle_t handle,
596                             gpio_mode_e mode,
597                             gpio_direction_e dir)
598 {
599     GPIO_NULL_PARAM_CHK(handle);
600 
601     /* config the gpio pin mode direction mask bits */
602     dw_gpio_pin_priv_t *gpio_pin_priv = handle;
603 
604     /* convert portidx to port handle */
605     dw_gpio_priv_t *gpio_priv = &gpio_handle[gpio_pin_priv->portidx];
606 
607     gpio_priv->mode = mode;
608     gpio_priv->dir = dir;
609     gpio_priv->mask = 1 << gpio_pin_priv->idx;
610 
611     uint32_t ret = gpio_set_direction(gpio_priv, dir);
612 
613     if (ret) {
614         return ret;
615     }
616 
617     return 0;
618 
619 }
620 
621 /**
622   \brief       Set one or zero to the selected GPIO pin.
623   \param[in]   handle       gpio pin handle to operate.
624   \param[in]   value     the value to be set
625   \return      error code
626 */
csi_gpio_pin_write(gpio_pin_handle_t handle,bool value)627 int32_t csi_gpio_pin_write(gpio_pin_handle_t handle, bool value)
628 {
629     GPIO_NULL_PARAM_CHK(handle);
630 
631     dw_gpio_pin_priv_t *gpio_pin_priv = handle;
632 
633     /* convert portidx to port handle */
634     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
635 
636     uint8_t offset = gpio_pin_priv->idx;
637     uint32_t port_value = value << offset;
638 
639     port_handle->value = port_value;
640     gpio_write(port_handle, (1 << offset));
641 
642     return 0;
643 
644 }
645 
646 /**
647   \brief       Get the value of  selected GPIO pin.
648   \param[in]   handle       gpio pin handle to operate.
649   \param[out]  value     buf to store the pin value
650   \return      error code
651 */
csi_gpio_pin_read(gpio_pin_handle_t handle,bool * value)652 int32_t csi_gpio_pin_read(gpio_pin_handle_t handle, bool *value)
653 {
654     GPIO_NULL_PARAM_CHK(handle);
655     GPIO_NULL_PARAM_CHK(value);
656 
657     dw_gpio_pin_priv_t *gpio_pin_priv = handle;
658     uint32_t port_value;
659     uint8_t offset = gpio_pin_priv->idx;
660 
661     /* convert portidx to port handle */
662     dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx];
663 
664     gpio_read(port_handle, &port_value);
665     *value = (port_value & (1 << offset)) >> offset;
666 
667     return 0;
668 }
669 
670 /**
671   \brief       set GPIO interrupt mode.
672   \param[in]   handle       gpio pin handle to operate.
673   \param[in]   mode      the irq mode to be set
674   \param[in]   enable    the enable flag
675   \return      error code
676 */
csi_gpio_pin_set_irq(gpio_pin_handle_t handle,gpio_irq_mode_e mode,bool enable)677 int32_t csi_gpio_pin_set_irq(gpio_pin_handle_t handle, gpio_irq_mode_e mode, bool enable)
678 {
679     GPIO_NULL_PARAM_CHK(handle);
680 
681     uint32_t ret = 0;
682 
683     if (enable) {
684         ret = gpio_set_irq_mode(handle, mode);
685 
686         if (ret) {
687             return ret;
688         }
689 
690         gpio_irq_enable(handle);
691 
692     } else {
693         gpio_irq_disable(handle);
694 
695     }
696 
697     return ret;
698 
699 }
700