s5j/gpio: split GPIO driver into two parts
authorHeesub Shin <heesub.shin@samsung.com>
Mon, 10 Apr 2017 05:15:24 +0000 (14:15 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Tue, 18 Apr 2017 03:02:14 +0000 (12:02 +0900)
This commits splits the GPIO driver into two parts. The first part will
handle GPIO pinmux control and the other will have lower-half driver
implementation. This is a preparation step for redesigning GPIO stuff.
Subsequent commits will rework GPIO things.

Change-Id: Id90d6a806dc6ede98b6cf5b3c5d431152a7fb17b
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
os/arch/arm/src/s5j/Make.defs
os/arch/arm/src/s5j/s5j_gpio.c
os/arch/arm/src/s5j/s5j_gpio.h
os/arch/arm/src/s5j/s5j_gpio_lowerhalf.c [new file with mode: 0644]

index c354df1..6e5f3e6 100644 (file)
@@ -121,9 +121,11 @@ endif
 CHIP_CSRCS += s5j_boot.c s5j_irq.c
 CHIP_CSRCS += s5j_serial.c
 CHIP_CSRCS += s5j_mac.c
+
 ifeq ($(CONFIG_S5J_GPIO),y)
-CHIP_CSRCS += s5j_gpio.c
+CHIP_CSRCS += s5j_gpio.c s5j_gpio_lowerhalf.c
 endif
+
 ifeq ($(CONFIG_S5J_SPI),y)
 CHIP_CSRCS += s5j_spi.c
 endif
index 7512034..ac5e3ba 100644 (file)
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
-#define EINT_INDEX             (57)
-#define NUM_EINT               (3)
-#define NUM_GPIO        (67)
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-struct s5j_gpio_priv {
-       int gpio;
-       int idx;
-       int isr_num;
-};
 
 /****************************************************************************
  * Private Functions prototypes
  ****************************************************************************/
-static struct gpio_bank *gpio_to_bank(int gpio);
 static void *__gpio_to_eint_base(int gpio);
 static unsigned __gpio_to_eint_bank(int gpio);
 static void *__gpio_eint_filter_get_addr(int gpio);
 static void *__gpio_eint_get_addr(int gpio, unsigned offset);
-static void s5j_gpio_callback_wqueue(FAR void *arg);
-static void s5j_gpio_poll_expiry(int argc, uint32_t arg, ...);
-static int s5j_gpio_irq_handler(int irq, void *context, void *arg);
-static void s5j_gpio_enable_irq(struct gpio_dev_s *dev);
-static void s5j_gpio_disable_irq(struct gpio_dev_s *dev);
-static u32 gpio_get_irq_id(int gpio);
-static const char *gpio_bank_name(int gpio);
-static int s5j_gpio_open(FAR struct gpio_dev_s *dev);
-static int s5j_gpio_close(FAR struct gpio_dev_s *dev);
-static int s5j_gpio_get(FAR struct gpio_dev_s *dev);
-static void s5j_gpio_set(FAR struct gpio_dev_s *dev, FAR unsigned int value);
-static int s5j_gpio_ctrl(struct gpio_dev_s *dev, int cmd, unsigned long args);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
-static const struct gpio_ops_s s5j_gpio_ops = {
-       .open  = s5j_gpio_open,
-       .close = s5j_gpio_close,
-       .set   = s5j_gpio_set,
-       .get   = s5j_gpio_get,
-       .ctrl  = s5j_gpio_ctrl
-};
-
-static struct gpio_dev_s *s5j_gpio_all[NUM_GPIO];
 
 /****************************************************************************
  * Public Data
  ****************************************************************************/
-#if defined(CONFIG_ARCH_CHIP_S5JT200)
 static struct gpio_bank s5jt200_gpio_bank[] = {
        [GPP0] = {
                .name = "GPP0",
@@ -224,41 +190,13 @@ static struct gpio_bank s5jt200_gpio_bank[] = {
                .group_type = GPIO_GROUP_COMMON,
        },
 };
-#endif
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
-
-
 /****************************************************************************
- * Name: gpio_to_bank 
- *
- * Description:
- *  Converts gpio port index into gpio bank structure address 
- *
- * Input Parameters:
- *  gpio - port id
- *
- * Returned Value:
- *  gpio bank structure address
- ****************************************************************************/
-static struct gpio_bank *gpio_to_bank(int gpio)
-{
-       unsigned bank;
-
-       bank = s5j_gpio_bank(gpio);
-
-       if (!gpio_valid(gpio)) {
-               return NULL;
-       }
-
-       return s5jt200_gpio_bank + bank;
-}
-
-/****************************************************************************
- * Name: __gpio_to_eint_base 
+ * Name: __gpio_to_eint_base
  *
  * Description:
  *  Converts gpio port index into eint base address
@@ -280,9 +218,8 @@ static void *__gpio_to_eint_base(int gpio)
        return gb->base;
 }
 
-
 /****************************************************************************
- * Name: __gpio_to_eint_bank 
+ * Name: __gpio_to_eint_bank
  *
  * Description:
  *  Converts gpio port index into eint bank
@@ -306,7 +243,6 @@ static unsigned __gpio_to_eint_bank(int gpio)
        }
 }
 
-
 /****************************************************************************
  * Name: __gpio_eint_filter_get_addr
  *
@@ -337,7 +273,7 @@ static void *__gpio_eint_filter_get_addr(int gpio)
  *
  * Input Parameters:
  *  gpio - port id
- *  offset - EINT CON/FLTCON/MASK/PEND offset addr 
+ *  offset - EINT CON/FLTCON/MASK/PEND offset addr
  *
  * Returned Value:
  *  Address
@@ -366,458 +302,8 @@ static void *__gpio_eint_get_addr(int gpio, unsigned offset)
 }
 
 /****************************************************************************
- * Name: s5j_gpio_callback_wqueue
- *
- * Description:
- *  Callback function assigned by s5j_gpio_poll_expiry, to execute by work queue
- *
- * Input Parameters:
- *  arg - arguments
- * 
- * Returned Value:
- *  None
- ****************************************************************************/
-static void s5j_gpio_callback_wqueue(FAR void *arg)
-{
-       struct gpio_dev_s *dev;
-
-       dev = (struct gpio_dev_s *)arg;
-
-       if (dev->callback) {
-               dev->callback();
-       }
-}
-
-/****************************************************************************
- * Function: s5j_poll_expiry
- *
- * Description:
- *   Periodic timer handler.  Called from the timer interrupt handler.
- *
- * Parameters:
- *   argc - The number of available arguments
- *   arg  - The first argument
- *
- * Returned Value:
- *   None
- *
- * Assumptions:
- *   Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void s5j_gpio_poll_expiry(int argc, uint32_t arg, ...)
-{
-       const uint32_t S5J_WDDELAY = 1 * CLK_TCK;
-       FAR struct gpio_dev_s *dev = (FAR struct gpio_dev_s *)arg;
-
-#ifdef CONFIG_SCHED_WORKQUEUE
-       if (work_available(&dev->work)) {
-               /* Schedule to perform the interrupt processing on the worker thread. */
-
-               work_queue(HPWORK, &dev->work, s5j_gpio_callback_wqueue, dev, 0);
-       } else {
-#endif
-               /* No.. Just re-start the watchdog poll timer, missing one polling
-                * cycle.
-                */
-
-               (void)wd_start(dev->wdog, S5J_WDDELAY, s5j_gpio_poll_expiry, 1, (uint32_t)dev);
-#ifdef CONFIG_SCHED_WORKQUEUE
-       }
-#endif
-}
-
-/****************************************************************************
- * Name: s5j_gpio_irq_handler
- *
- * Description:
- *  IRQ handler to assign to handle IRQ and perform gpio notify, if configured
- *
- * Input Parameters:
- *  irq - IRQ number
- *  context - pointer to a dedicated context structure
- * 
- * Returned Value:
- *  Ok
- *  -1, if Error
- *
- ****************************************************************************/
-static int s5j_gpio_irq_handler(int irq, void *context, void *arg)
-{
-       int i;
-       struct gpio_dev_s *dev;
-
-       for (i = 0; i < NUM_GPIO; i++) {
-               if (s5j_gpio_all[i] && ((((struct s5j_gpio_priv *)(s5j_gpio_all[i]->priv))->isr_num) & 0x3ff) == irq) {
-                               break;
-               }
-       }
-
-       if (i == NUM_GPIO) {
-               return -1;
-       }
-
-       gpio_eint_clear_pending(((struct s5j_gpio_priv *)(s5j_gpio_all[i]->priv))->gpio);
-
-       dev = s5j_gpio_all[i];
-
-       if (dev->callback) {
-               s5j_gpio_poll_expiry(1, (uint32_t)dev);
-       }
-#ifdef CONFIG_GPIO
-#ifndef CONFIG_DISABLE_POLL
-       gpio_notify(s5j_gpio_all[i]);
-#endif
-#endif
-
-       return OK;
-}
-
-/****************************************************************************
- * Name: s5j_gpio_enable_irq
- *
- * Description:
- *  Enable IRQ
- *
- * Input Parameters:
- *  dev - GPIO device 
- * 
- * Returned Value:
- *  None
- *  
- *
- ****************************************************************************/
-static void s5j_gpio_enable_irq(struct gpio_dev_s *dev)
-{
-       int gpio;
-       int irq;
-       gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
-
-       gpio_cfg_pin(gpio, GPIO_IRQ);
-       gpio_eint_clear_pending(gpio);
-       gpio_eint_unmask(gpio);
-
-       irq = gpio_to_bank(gpio)->isr_num[s5j_gpio_port(gpio)];
-       (void)irq_attach(irq, (xcpt_t)s5j_gpio_irq_handler, NULL);
-       up_enable_irq(irq);
-}
-
-/****************************************************************************
- * Name: s5j_gpio_disable_irq
- *
- * Description:
- *  Disable IRQ
- *
- * Input Parameters:
- *  dev - GPIO device 
- * 
- * Returned Value:
- *  None
- *  
- *
- ****************************************************************************/
-static void s5j_gpio_disable_irq(struct gpio_dev_s *dev)
-{
-       int gpio;
-       int irq;
-       gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
-       gpio_eint_clear_pending(gpio);
-       gpio_eint_unmask(gpio);
-       irq = gpio_to_bank(gpio)->isr_num[s5j_gpio_port(gpio)];
-       up_disable_irq(irq);
-}
-
-
-
-/****************************************************************************
- * Name: gpio_get_irq_id
- *
- * Description:
- *  Return IRQ ID 
- *
- * Input Parameters:
- *  gpio - port id
- * 
- * Returned Value:
- *  irq ID  
- *  < 0, Error 
- *
- ****************************************************************************/
-static u32 gpio_get_irq_id(int gpio)
-{
-       unsigned port;
-       unsigned isr;
-       struct gpio_bank *gb = NULL;
-
-       if (!gpio_valid(gpio)) {
-               return -EINVAL;
-       }
-
-       gb = gpio_to_bank(gpio);
-       port = s5j_gpio_port(gpio);
-
-       isr = gb->isr_num[port];
-       if (!isr) {
-               isr = gb->isr_num[0];
-       }
-
-       return gpio_irq_id(gpio, isr);
-}
-
-/****************************************************************************
- * Name: gpio_bank_name
- *
- * Description:
- *  Find and return a gpio bank name from a gpio id
- *
- * Input Parameters:
- *  gpio - port id
- * 
- * Returned Value:
- *  gpio bank name
- *  NULL in case of error 
- *
- ****************************************************************************/
-static const char *gpio_bank_name(int gpio)
-{
-       struct gpio_bank *gb = gpio_to_bank(gpio);
-
-       if (!gb) {
-               return NULL;
-       }
-
-       return gb->name;
-}
-
-/****************************************************************************
- * Name: s5j_gpio_open 
- *
- * Description:
- *   Open GPIO port
- *
- * Input Parameters:
- *   dev - device
- *
- * Returned Value:
- *   == OK: Open success     
- *   == -EINVAL: invalid gpio
- ****************************************************************************/
-static int s5j_gpio_open(FAR struct gpio_dev_s *dev)
-{
-       return OK;
-}
-
-/****************************************************************************
- * Name: s5j_gpio_close 
- *
- * Description:
- *   Close GPIO port
- *
- * Input Parameters:
- *   dev - device
- *
- * Returned Value:
- *   == 0: close success     
- *   == -EINVAL: invalid gpio
- ****************************************************************************/
-static int s5j_gpio_close(FAR struct gpio_dev_s *dev)
-{
-       struct s5j_gpio_priv *priv = (struct s5j_gpio_priv *)(dev->priv);
-       int idx = priv->idx;
-       s5j_gpio_disable_irq(s5j_gpio_all[idx]);
-
-       if (NULL != dev->wdog) {
-               wd_cancel(dev->wdog);
-               dev->wdog = NULL;
-       }
-
-       return OK;
-}
-
-/****************************************************************************
- * Name: s5j_gpio_get
- *
- * Description:
- *   Get GPIO value
- *
- * Input Parameters:
- *   dev - device
- *
- * Returned Value:
- *   >= 0: gpio value        
- *   == -EINVAL: invalid gpio
- ****************************************************************************/
-static int s5j_gpio_get(FAR struct gpio_dev_s *dev)
-{
-       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
-       if (!gpio_valid(gpio)) {
-               return -EINVAL;
-       }
-       return gpio_get_value(gpio);
-}
-
-/****************************************************************************
- * Name: s5j_gpio_set
- *
- * Description:
- *   Set GPIO value
- *
- * Input Parameters:
- *   dev - device
- *   value - value to set
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-static void s5j_gpio_set(FAR struct gpio_dev_s *dev, FAR unsigned int value)
-{
-       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
-       gpio_set_value(gpio, value);
-}
-
-/****************************************************************************
- * Name: s5j_gpio_ctrl
- *
- * Description:
- *   GPIO IOCTRL function
- *
- * Input Parameters:
- *   dev - device
- *   cmd - ioctl command
- *   arg - ioctl argument
- *
- * Returned Value:
- *   >= 0: gpio ret value or OK
- *   == -EINVAL: invalid gpio
- *
- ****************************************************************************/
-static int s5j_gpio_ctrl(struct gpio_dev_s *dev, int cmd, unsigned long args)
-{
-       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
-       bool isenable = true;
-       GPIO_CB_FUNC func = (GPIO_CB_FUNC)args;
-
-       if (!gpio_valid(gpio)) {
-               return -EINVAL;
-       }
-       switch (cmd) {
-       case GPIO_CMD_SET_DIRECTION:
-               switch (args) {
-               case GPIO_DIRECTION_OUT:
-                       gpio_cfg_pin(gpio, GPIO_OUTPUT);
-                       break;
-               case GPIO_DIRECTION_IN:
-                       gpio_cfg_pin(gpio, GPIO_INPUT);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case GPIO_CMD_GET_DIRECTION:
-               return gpio_cfg_get_pin(gpio);
-               break;
-       case GPIO_CMD_SET_EDGE:
-               gpio_eint_set_filter(gpio, EINT_FILTER_DELAY, 0);
-               switch (args) {
-               case GPIO_EDGE_NONE:
-                       s5j_gpio_disable_irq(dev);
-                       isenable = false;
-                       break;
-               case GPIO_EDGE_BOTH:
-                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_BOTH);
-                       break;
-               case GPIO_EDGE_RISING:
-                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_RISING);
-                       break;
-               case GPIO_EDGE_FALLING:
-                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_FALLING);
-                       break;
-               case GPIO_LEVEL_LOW:
-                       gpio_eint_set_type(gpio, EINT_TYPE_LEVEL_LOW);
-                       break;
-               case GPIO_LEVEL_HIGH:
-                       gpio_eint_set_type(gpio, EINT_TYPE_LEVEL_HIGH);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               if (isenable) {
-                       s5j_gpio_enable_irq(dev);
-               }
-               break;
-       case GPIO_CMD_GET_EDGE:
-               switch (gpio_eint_get_type(gpio)) {
-               case EINT_TYPE_EDGE_BOTH:
-                       return GPIO_EDGE_BOTH;
-                       break;
-               case EINT_TYPE_EDGE_RISING:
-                       return GPIO_EDGE_RISING;
-                       break;
-               case EINT_TYPE_EDGE_FALLING:
-                       return GPIO_EDGE_FALLING;
-                       break;
-               case EINT_TYPE_LEVEL_LOW:
-                       return GPIO_LEVEL_LOW;
-                       break;
-               case EINT_TYPE_LEVEL_HIGH:
-                       return GPIO_LEVEL_HIGH;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case GPIO_CMD_SET_DRIVE:
-               switch (args) {
-               case GPIO_DRIVE_NONE:
-                       gpio_set_pull(gpio, GPIO_PULL_NONE);
-                       break;
-               case GPIO_DRIVE_PULLUP:
-                       gpio_set_pull(gpio, GPIO_PULL_UP);
-                       break;
-               case GPIO_DRIVE_PULLDOWN:
-                       gpio_set_pull(gpio, GPIO_PULL_DOWN);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case GPIO_CMD_GET_DRIVE:
-               switch (gpio_get_pull(gpio)) {
-               case GPIO_PULL_NONE:
-                       return GPIO_DRIVE_NONE;
-               case GPIO_PULL_UP:
-                       return GPIO_DRIVE_PULLUP;
-               case GPIO_PULL_DOWN:
-                       return GPIO_DRIVE_PULLDOWN;
-               default:
-                       return -EINVAL;
-               }
-               break;
-
-       case GPIO_CMD_SET_CALLBACK:
-               /* if someone creates wdog, we don't need to create again */
-
-               if (dev->wdog == NULL) {
-                       dev->wdog = wd_create();
-               }
-               dev->callback = func;
-               break;
-
-       default:
-               return -EINVAL;
-               break;
-       }
-       return OK;
-}
-
-
-
-/****************************************************************************
  * Public Functions
  ****************************************************************************/
-
 /****************************************************************************
  * Name: gpio_valid
  *
@@ -826,10 +312,10 @@ static int s5j_gpio_ctrl(struct gpio_dev_s *dev, int cmd, unsigned long args)
  *
  * Input Parameters:
  *  gpio - port id
- * 
+ *
  * Returned Value:
- *  == 1: valid gpio  
- *  == 0: invalid gpio 
+ *  == 1: valid gpio
+ *  == 0: invalid gpio
  *
  ****************************************************************************/
 int gpio_valid(int gpio)
@@ -867,7 +353,7 @@ int gpio_valid(int gpio)
  * Input Parameters:
  *  gpio - port id
  *  cfg        a mode of gpio pin(input/output/function/irq)
- * 
+ *
  * Returned Value:
  *  == 0: success
  *  == -EINVAL: invalid gpio
@@ -893,7 +379,6 @@ int gpio_cfg_pin(int gpio, int cfg)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_cfg_get_pin
  *
@@ -902,7 +387,7 @@ int gpio_cfg_pin(int gpio, int cfg)
  *
  * Input Parameters:
  *  gpio - port id
- *  
+ *
  * Returned Value:
  *  == 0: input
  *  == 1: output
@@ -928,7 +413,6 @@ int gpio_cfg_get_pin(int gpio)
        return ((value >> (port << 2)) & 0xF);
 }
 
-
 /****************************************************************************
  * Name: gpio_direction_output
  *
@@ -942,7 +426,7 @@ int gpio_cfg_get_pin(int gpio)
  * Returned Value:
  *  == 0: success
  *  == -EINVAL: invalid gpio
- *  
+ *
  ****************************************************************************/
 int gpio_direction_output(int gpio, int high)
 {
@@ -975,11 +459,11 @@ int gpio_direction_output(int gpio, int high)
  *
  * Input Parameters:
  *  gpio - port id
- *  
+ *
  * Returned Value:
  *  == 0: success
  *  == -EINVAL: invalid gpio
- *  
+ *
  ****************************************************************************/
 int gpio_direction_input(int gpio)
 {
@@ -999,7 +483,7 @@ int gpio_direction_input(int gpio)
  * Returned Value:
  *  == 0: success
  *  == -EINVAL: invalid gpio
- *  
+ *
  ****************************************************************************/
 int gpio_set_value(int gpio, int high)
 {
@@ -1024,7 +508,6 @@ int gpio_set_value(int gpio, int high)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_get_value
  *
@@ -1033,10 +516,9 @@ int gpio_set_value(int gpio, int high)
  *
  * Input Parameters:
  *  gpio - port id
- *  
  *
  * Returned Value:
- *  == 1: gpio read as high== 0: success            
+ *  == 1: gpio read as high== 0: success
  *  == 0: gpio read as low == -EINVAL: invalid gpio
  *   < 0: error
  ****************************************************************************/
@@ -1057,7 +539,6 @@ int gpio_get_value(int gpio)
        return (value >> port) & 1;
 }
 
-
 /****************************************************************************
  * Name: gpio_set_pull
  *
@@ -1069,8 +550,8 @@ int gpio_get_value(int gpio)
  *  mode - gpio pin mode(pull up/pull down)
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_set_pull(int gpio, int mode)
 {
@@ -1112,11 +593,11 @@ int gpio_set_pull(int gpio, int mode)
  *
  * Input Parameters:
  *  gpio - port id
- *  
+ *
  *
  * Returned Value:
- *  >= 0: pull up down data 
- *   
+ *  >= 0: pull up down data
+ *
  ****************************************************************************/
 int gpio_get_pull(int gpio)
 {
@@ -1147,7 +628,7 @@ int gpio_get_pull(int gpio)
  *  mode - strength of gpio pin mode
  *
  * Returned Value:
- *   == 0: success           
+ *   == 0: success
  *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_set_drv(int gpio, int mode)
@@ -1189,7 +670,7 @@ int gpio_set_drv(int gpio, int mode)
  *
  * Input Parameters:
  *  gpio - port id
- *   
+ *
  *
  * Returned Value:
  *   <= 0: strength of gpio pin mode
@@ -1212,7 +693,6 @@ int gpio_get_drv(int gpio)
        return value;
 }
 
-
 /****************************************************************************
  * Name: gpio_set_rate
  *
@@ -1221,11 +701,11 @@ int gpio_get_drv(int gpio)
  *
  * Input Parameters:
  *  gpio - port id
- *  mode - slew rate of a gpio pin 
+ *  mode - slew rate of a gpio pin
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_set_rate(int gpio, int mode)
 {
@@ -1266,8 +746,8 @@ int gpio_set_rate(int gpio, int mode)
  *  cfg - configuration a power down mode of a gpio pin
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_cfg_pin_pdn(int gpio, int cfg)
 {
@@ -1290,7 +770,6 @@ int gpio_cfg_pin_pdn(int gpio, int cfg)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_set_pull_pdn
  *
@@ -1302,8 +781,8 @@ int gpio_cfg_pin_pdn(int gpio, int cfg)
  *  mode - gpio pin mode(pull up/pull down)
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_set_pull_pdn(int gpio, int mode)
 {
@@ -1334,7 +813,6 @@ int gpio_set_pull_pdn(int gpio, int mode)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_eint_mask
  *
@@ -1345,8 +823,8 @@ int gpio_set_pull_pdn(int gpio, int mode)
  *  gpio - port id
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_mask(int gpio)
 {
@@ -1378,8 +856,8 @@ int gpio_eint_mask(int gpio)
  *  gpio - port id
  *
  * Returned Value:
- *  == 0: success            
- *  == -EINVAL: invalid gpio 
+ *  == 0: success
+ *  == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_unmask(int gpio)
 {
@@ -1411,8 +889,8 @@ int gpio_eint_unmask(int gpio)
  *  gpio - port id
  *
  * Returned Value:
- *  == true: gpio external interrupt is pending      
- *  == false: gpio external interrupt is not pending 
+ *  == true: gpio external interrupt is pending
+ *  == false: gpio external interrupt is not pending
  ****************************************************************************/
 bool gpio_eint_ispending(int gpio)
 {
@@ -1428,7 +906,6 @@ bool gpio_eint_ispending(int gpio)
        return (pend & (1 << port)) ? true : false;
 }
 
-
 /****************************************************************************
  * Name: gpio_eint_clear_pending
  *
@@ -1439,8 +916,8 @@ bool gpio_eint_ispending(int gpio)
  *   gpio - port id
  *
  * Returned Value:
- *   >= 0: success 
- *   == -EINVAL: invalid gpio              
+ *   >= 0: success
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_clear_pending(int gpio)
 {
@@ -1468,7 +945,6 @@ int gpio_eint_clear_pending(int gpio)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_eint_enable_filter
  *
@@ -1479,8 +955,8 @@ int gpio_eint_clear_pending(int gpio)
  *   gpio - port id
  *
  * Returned Value:
- *   >= 0: success 
- *   == -EINVAL: invalid gpio              
+ *   >= 0: success
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_enable_filter(int gpio)
 {
@@ -1508,7 +984,6 @@ int gpio_eint_enable_filter(int gpio)
        return 0;
 }
 
-
 /****************************************************************************
  * Name: gpio_eint_disable_filter
  *
@@ -1519,8 +994,8 @@ int gpio_eint_enable_filter(int gpio)
  *   gpio - port id
  *
  * Returned Value:
- *   >= 0: success 
- *   == -EINVAL: invalid gpio              
+ *   >= 0: success
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_disable_filter(int gpio)
 {
@@ -1556,12 +1031,12 @@ int gpio_eint_disable_filter(int gpio)
  *
  * Input Parameters:
  *   gpio - port id
- *   type - filter type(delay/digital) 
+ *   type - filter type(delay/digital)
  *   width - filter width(it will be ignored when filter type is delay)
  *
  * Returned Value:
- *   >= 0: success 
- *   == -EINVAL: invalid gpio              
+ *   >= 0: success
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_set_filter(int gpio, unsigned type, unsigned width)
 {
@@ -1624,12 +1099,12 @@ int gpio_eint_set_filter(int gpio, unsigned type, unsigned width)
  *   Set edge/level type of a gpio external interrurt
  *
  * Input Parameters:
- *   gpio - port id 
+ *   gpio - port id
  *   type - eint interrupt type (edge/level)
  *
  * Returned Value:
- *   >= 0: success 
- *   == -EINVAL: invalid gpio              
+ *   >= 0: success
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_set_type(int gpio, unsigned type)
 {
@@ -1680,7 +1155,7 @@ int gpio_eint_set_type(int gpio, unsigned type)
  *
  * Returned Value:
  *   >= 0: eint interrupt type (edge/level)
- *   == -EINVAL: invalid gpio              
+ *   == -EINVAL: invalid gpio
  ****************************************************************************/
 int gpio_eint_get_type(int gpio)
 {
@@ -1702,83 +1177,27 @@ int gpio_eint_get_type(int gpio)
        return ctrl;
 }
 
-
 /****************************************************************************
- * Name: up_create_gpio
+ * Name: gpio_to_bank
  *
  * Description:
- *  Creates GPIO port and expose it to file system: dev/gpioXX 
+ *  Converts gpio port index into gpio bank structure address
  *
  * Input Parameters:
  *  gpio - port id
  *
  * Returned Value:
- *  0
+ *  gpio bank structure address
  ****************************************************************************/
-
-int up_create_gpio(int32_t idx)
+struct gpio_bank *gpio_to_bank(int gpio)
 {
-#ifdef CONFIG_GPIO
-       char path[20];
-       struct s5j_gpio_priv *pgpio;
-       int bank = 0;
-       int port;
-       int idx_table[] = { 7, 15, 22, 28, 36, 44, 52, 56, 59, 63, 66 };
-
-       pgpio = (struct s5j_gpio_priv *)kmm_malloc(sizeof(struct s5j_gpio_priv));
-       s5j_gpio_all[idx] = (struct gpio_dev_s *)kmm_malloc(sizeof(struct gpio_dev_s));
-       s5j_gpio_all[idx]->ops = &s5j_gpio_ops;
-       s5j_gpio_all[idx]->priv = pgpio;
-       s5j_gpio_all[idx]->wdog = NULL;
-       s5j_gpio_all[idx]->callback = NULL;
-
-       for (bank = 0; bank < sizeof(idx_table) / sizeof(int); bank++) {
-               if (idx_table[bank] >= idx) {
-                       break;
-               }
-       }
-       if (bank) {
-               port = idx - (idx_table[bank - 1] + 1);
-       } else {
-               port = idx;
-       }
-       pgpio->gpio = s5j_gpio(bank, port);
-       pgpio->idx = idx;
-       pgpio->isr_num = gpio_get_irq_id(pgpio->gpio);
-       snprintf(path, sizeof(path), "/dev/gpio%d", idx);
-       gpio_register(path, s5j_gpio_all[idx]);
-       return 0;
-#else
-       return 0;
-#endif
-}
+       unsigned bank;
 
-/****************************************************************************
- * Name: up_destroy_gpio 
- *
- * Description:
- *   Destroy GPIO idx entry, release allocated priv memory. 
- *
- * Input Parameters:
- *   idx - GPIO index
- *
- * Returned Value:
- *   OK
- *
- ****************************************************************************/
-int up_destroy_gpio(int32_t idx)
-{
-       struct s5j_gpio_priv *priv = (struct s5j_gpio_priv *)(s5j_gpio_all[idx]->priv);
-       if (priv) {
-               kmm_free(priv);
-       }
-       s5j_gpio_all[idx]->ops = NULL;
-       s5j_gpio_all[idx]->priv = NULL;
+       bank = s5j_gpio_bank(gpio);
 
-       if (s5j_gpio_all[idx]->wdog) {
-               wd_cancel(s5j_gpio_all[idx]->wdog);
+       if (!gpio_valid(gpio)) {
+               return NULL;
        }
-       kmm_free(s5j_gpio_all[idx]);
 
-       return OK;
+       return s5jt200_gpio_bank + bank;
 }
index 63741cd..d3a7a73 100644 (file)
@@ -232,6 +232,7 @@ int gpio_eint_disable_filter(int gpio);
 int gpio_eint_set_filter(int gpio, unsigned type, unsigned width);
 int gpio_eint_set_type(int gpio, unsigned type);
 int gpio_eint_get_type(int gpio);
+struct gpio_bank *gpio_to_bank(int gpio);
 
 #if defined(__cplusplus)
 }
diff --git a/os/arch/arm/src/s5j/s5j_gpio_lowerhalf.c b/os/arch/arm/src/s5j/s5j_gpio_lowerhalf.c
new file mode 100644 (file)
index 0000000..626fe6a
--- /dev/null
@@ -0,0 +1,630 @@
+/****************************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * os/arch/arm/src/s5j/s5j_gpio_lowerhalf.c
+ *
+ *   Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <arch/irq.h>
+#include <tinyara/gpio.h>
+#include <tinyara/wdog.h>
+#include <tinyara/wqueue.h>
+#include <tinyara/kmalloc.h>
+
+#include "up_arch.h"
+#include "s5j_gpio.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+#define NUM_GPIO       67
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+struct s5j_gpio_priv {
+       int gpio;
+       int idx;
+       int isr_num;
+};
+
+/****************************************************************************
+ * Private Functions prototypes
+ ****************************************************************************/
+static int s5j_gpio_open(FAR struct gpio_dev_s *dev);
+static int s5j_gpio_close(FAR struct gpio_dev_s *dev);
+static int s5j_gpio_get(FAR struct gpio_dev_s *dev);
+static void s5j_gpio_set(FAR struct gpio_dev_s *dev, FAR unsigned int value);
+static int s5j_gpio_ctrl(struct gpio_dev_s *dev, int cmd, unsigned long args);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+static const struct gpio_ops_s s5j_gpio_ops = {
+       .open  = s5j_gpio_open,
+       .close = s5j_gpio_close,
+       .set   = s5j_gpio_set,
+       .get   = s5j_gpio_get,
+       .ctrl  = s5j_gpio_ctrl
+};
+
+static struct gpio_dev_s *s5j_gpio_all[NUM_GPIO];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_gpio_callback_wqueue
+ *
+ * Description:
+ *   Callback function assigned by s5j_gpio_poll_expiry, to execute by work
+ *   queue
+ *
+ * Input Parameters:
+ *  arg - arguments
+ *
+ * Returned Value:
+ *  None
+ *
+ ****************************************************************************/
+static void s5j_gpio_callback_wqueue(FAR void *arg)
+{
+       struct gpio_dev_s *dev;
+
+       dev = (struct gpio_dev_s *)arg;
+
+       if (dev->callback) {
+               dev->callback();
+       }
+}
+
+/****************************************************************************
+ * Function: s5j_poll_expiry
+ *
+ * Description:
+ *   Periodic timer handler.  Called from the timer interrupt handler.
+ *
+ * Parameters:
+ *   argc - The number of available arguments
+ *   arg  - The first argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+static void s5j_gpio_poll_expiry(int argc, uint32_t arg, ...)
+{
+       const uint32_t S5J_WDDELAY = 1 * CLK_TCK;
+       FAR struct gpio_dev_s *dev = (FAR struct gpio_dev_s *)arg;
+
+#ifdef CONFIG_SCHED_WORKQUEUE
+       if (work_available(&dev->work)) {
+               /* Schedule to perform the interrupt processing on the worker thread. */
+               work_queue(HPWORK, &dev->work, s5j_gpio_callback_wqueue, dev, 0);
+       } else {
+#endif
+               /*
+                * No.. Just re-start the watchdog poll timer, missing one polling
+                * cycle.
+                */
+               (void)wd_start(dev->wdog, S5J_WDDELAY, s5j_gpio_poll_expiry, 1, (uint32_t)dev);
+#ifdef CONFIG_SCHED_WORKQUEUE
+       }
+#endif
+}
+
+/****************************************************************************
+ * Name: gpio_get_irq_id
+ *
+ * Description:
+ *  Return IRQ ID
+ *
+ * Input Parameters:
+ *  gpio - port id
+ *
+ * Returned Value:
+ *  irq ID
+ *  < 0, Error
+ *
+ ****************************************************************************/
+static u32 gpio_get_irq_id(int gpio)
+{
+       unsigned port;
+       unsigned isr;
+       struct gpio_bank *gb = NULL;
+
+       if (!gpio_valid(gpio)) {
+               return -EINVAL;
+       }
+
+       gb = gpio_to_bank(gpio);
+       port = s5j_gpio_port(gpio);
+
+       isr = gb->isr_num[port];
+       if (!isr) {
+               isr = gb->isr_num[0];
+       }
+
+       return gpio_irq_id(gpio, isr);
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_irq_handler
+ *
+ * Description:
+ *  IRQ handler to assign to handle IRQ and perform gpio notify, if configured
+ *
+ * Input Parameters:
+ *  irq - IRQ number
+ *  context - pointer to a dedicated context structure
+ *
+ * Returned Value:
+ *  Ok
+ *  -1, if Error
+ *
+ ****************************************************************************/
+static int s5j_gpio_irq_handler(int irq, void *context, void *arg)
+{
+       int i;
+       struct gpio_dev_s *dev;
+
+       for (i = 0; i < NUM_GPIO; i++) {
+               if (s5j_gpio_all[i] && ((((struct s5j_gpio_priv *)(s5j_gpio_all[i]->priv))->isr_num) & 0x3ff) == irq) {
+                               break;
+               }
+       }
+
+       if (i == NUM_GPIO) {
+               return -1;
+       }
+
+       gpio_eint_clear_pending(((struct s5j_gpio_priv *)(s5j_gpio_all[i]->priv))->gpio);
+
+       dev = s5j_gpio_all[i];
+
+       if (dev->callback) {
+               s5j_gpio_poll_expiry(1, (uint32_t)dev);
+       }
+
+#ifdef CONFIG_GPIO
+#ifndef CONFIG_DISABLE_POLL
+       gpio_notify(s5j_gpio_all[i]);
+#endif
+#endif
+
+       return OK;
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_enable_irq
+ *
+ * Description:
+ *   Enable IRQ
+ *
+ * Input Parameters:
+ *   dev - GPIO device
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+static void s5j_gpio_enable_irq(struct gpio_dev_s *dev)
+{
+       int gpio;
+       int irq;
+
+       gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
+
+       gpio_cfg_pin(gpio, GPIO_IRQ);
+       gpio_eint_clear_pending(gpio);
+       gpio_eint_unmask(gpio);
+
+       irq = gpio_to_bank(gpio)->isr_num[s5j_gpio_port(gpio)];
+       (void)irq_attach(irq, (xcpt_t)s5j_gpio_irq_handler, NULL);
+       up_enable_irq(irq);
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_disable_irq
+ *
+ * Description:
+ *  Disable IRQ
+ *
+ * Input Parameters:
+ *  dev - GPIO device
+ *
+ * Returned Value:
+ *  None
+ *
+ ****************************************************************************/
+static void s5j_gpio_disable_irq(struct gpio_dev_s *dev)
+{
+       int gpio;
+       int irq;
+
+       gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
+       gpio_eint_clear_pending(gpio);
+       gpio_eint_unmask(gpio);
+       irq = gpio_to_bank(gpio)->isr_num[s5j_gpio_port(gpio)];
+       up_disable_irq(irq);
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_open
+ *
+ * Description:
+ *   Open GPIO port
+ *
+ * Input Parameters:
+ *   dev - device
+ *
+ * Returned Value:
+ *   == OK: Open success
+ *   == -EINVAL: invalid gpio
+ ****************************************************************************/
+static int s5j_gpio_open(FAR struct gpio_dev_s *dev)
+{
+       return OK;
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_close
+ *
+ * Description:
+ *   Close GPIO port
+ *
+ * Input Parameters:
+ *   dev - device
+ *
+ * Returned Value:
+ *   == 0: close success
+ *   == -EINVAL: invalid gpio
+ ****************************************************************************/
+static int s5j_gpio_close(FAR struct gpio_dev_s *dev)
+{
+       struct s5j_gpio_priv *priv = (struct s5j_gpio_priv *)(dev->priv);
+       int idx = priv->idx;
+
+       s5j_gpio_disable_irq(s5j_gpio_all[idx]);
+
+       if (NULL != dev->wdog) {
+               wd_cancel(dev->wdog);
+               dev->wdog = NULL;
+       }
+
+       return OK;
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_get
+ *
+ * Description:
+ *   Get GPIO value
+ *
+ * Input Parameters:
+ *   dev - device
+ *
+ * Returned Value:
+ *   >= 0: gpio value
+ *   == -EINVAL: invalid gpio
+ ****************************************************************************/
+static int s5j_gpio_get(FAR struct gpio_dev_s *dev)
+{
+       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
+
+       if (!gpio_valid(gpio)) {
+               return -EINVAL;
+       }
+
+       return gpio_get_value(gpio);
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_set
+ *
+ * Description:
+ *   Set GPIO value
+ *
+ * Input Parameters:
+ *   dev - device
+ *   value - value to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+static void s5j_gpio_set(FAR struct gpio_dev_s *dev, FAR unsigned int value)
+{
+       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
+       gpio_set_value(gpio, value);
+}
+
+/****************************************************************************
+ * Name: s5j_gpio_ctrl
+ *
+ * Description:
+ *   GPIO IOCTRL function
+ *
+ * Input Parameters:
+ *   dev - device
+ *   cmd - ioctl command
+ *   arg - ioctl argument
+ *
+ * Returned Value:
+ *   >= 0: gpio ret value or OK
+ *   == -EINVAL: invalid gpio
+ *
+ ****************************************************************************/
+static int s5j_gpio_ctrl(struct gpio_dev_s *dev, int cmd, unsigned long args)
+{
+       int gpio = ((struct s5j_gpio_priv *)(dev->priv))->gpio;
+       bool isenable = true;
+
+       GPIO_CB_FUNC func = (GPIO_CB_FUNC)args;
+
+       if (!gpio_valid(gpio)) {
+               return -EINVAL;
+       }
+
+       switch (cmd) {
+       case GPIO_CMD_SET_DIRECTION:
+               switch (args) {
+               case GPIO_DIRECTION_OUT:
+                       gpio_cfg_pin(gpio, GPIO_OUTPUT);
+                       break;
+               case GPIO_DIRECTION_IN:
+                       gpio_cfg_pin(gpio, GPIO_INPUT);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       case GPIO_CMD_GET_DIRECTION:
+               return gpio_cfg_get_pin(gpio);
+               break;
+
+       case GPIO_CMD_SET_EDGE:
+               gpio_eint_set_filter(gpio, EINT_FILTER_DELAY, 0);
+               switch (args) {
+               case GPIO_EDGE_NONE:
+                       s5j_gpio_disable_irq(dev);
+                       isenable = false;
+                       break;
+               case GPIO_EDGE_BOTH:
+                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_BOTH);
+                       break;
+               case GPIO_EDGE_RISING:
+                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_RISING);
+                       break;
+               case GPIO_EDGE_FALLING:
+                       gpio_eint_set_type(gpio, EINT_TYPE_EDGE_FALLING);
+                       break;
+               case GPIO_LEVEL_LOW:
+                       gpio_eint_set_type(gpio, EINT_TYPE_LEVEL_LOW);
+                       break;
+               case GPIO_LEVEL_HIGH:
+                       gpio_eint_set_type(gpio, EINT_TYPE_LEVEL_HIGH);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (isenable) {
+                       s5j_gpio_enable_irq(dev);
+               }
+               break;
+
+       case GPIO_CMD_GET_EDGE:
+               switch (gpio_eint_get_type(gpio)) {
+               case EINT_TYPE_EDGE_BOTH:
+                       return GPIO_EDGE_BOTH;
+                       break;
+               case EINT_TYPE_EDGE_RISING:
+                       return GPIO_EDGE_RISING;
+                       break;
+               case EINT_TYPE_EDGE_FALLING:
+                       return GPIO_EDGE_FALLING;
+                       break;
+               case EINT_TYPE_LEVEL_LOW:
+                       return GPIO_LEVEL_LOW;
+                       break;
+               case EINT_TYPE_LEVEL_HIGH:
+                       return GPIO_LEVEL_HIGH;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       case GPIO_CMD_SET_DRIVE:
+               switch (args) {
+               case GPIO_DRIVE_NONE:
+                       gpio_set_pull(gpio, GPIO_PULL_NONE);
+                       break;
+               case GPIO_DRIVE_PULLUP:
+                       gpio_set_pull(gpio, GPIO_PULL_UP);
+                       break;
+               case GPIO_DRIVE_PULLDOWN:
+                       gpio_set_pull(gpio, GPIO_PULL_DOWN);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case GPIO_CMD_GET_DRIVE:
+               switch (gpio_get_pull(gpio)) {
+               case GPIO_PULL_NONE:
+                       return GPIO_DRIVE_NONE;
+               case GPIO_PULL_UP:
+                       return GPIO_DRIVE_PULLUP;
+               case GPIO_PULL_DOWN:
+                       return GPIO_DRIVE_PULLDOWN;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       case GPIO_CMD_SET_CALLBACK:
+               /* if someone creates wdog, we don't need to create again */
+               if (dev->wdog == NULL) {
+                       dev->wdog = wd_create();
+               }
+
+               dev->callback = func;
+               break;
+
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_create_gpio
+ *
+ * Description:
+ *   Creates GPIO port and expose it to file system: dev/gpioXX
+ *
+ * Input Parameters:
+ *   gpio - port id
+ *
+ * Returned Value:
+ *   0
+ ****************************************************************************/
+int up_create_gpio(int32_t idx)
+{
+#ifdef CONFIG_GPIO
+       char path[20];
+       struct s5j_gpio_priv *pgpio;
+       int bank = 0;
+       int port;
+       int idx_table[] = { 7, 15, 22, 28, 36, 44, 52, 56, 59, 63, 66 };
+
+       pgpio = (struct s5j_gpio_priv *)kmm_malloc(sizeof(struct s5j_gpio_priv));
+       s5j_gpio_all[idx] = (struct gpio_dev_s *)kmm_malloc(sizeof(struct gpio_dev_s));
+       s5j_gpio_all[idx]->ops = &s5j_gpio_ops;
+       s5j_gpio_all[idx]->priv = pgpio;
+       s5j_gpio_all[idx]->wdog = NULL;
+       s5j_gpio_all[idx]->callback = NULL;
+
+       for (bank = 0; bank < sizeof(idx_table) / sizeof(int); bank++) {
+               if (idx_table[bank] >= idx) {
+                       break;
+               }
+       }
+
+       if (bank) {
+               port = idx - (idx_table[bank - 1] + 1);
+       } else {
+               port = idx;
+       }
+
+       pgpio->gpio = s5j_gpio(bank, port);
+       pgpio->idx = idx;
+       pgpio->isr_num = gpio_get_irq_id(pgpio->gpio);
+       snprintf(path, sizeof(path), "/dev/gpio%d", idx);
+       gpio_register(path, s5j_gpio_all[idx]);
+#endif
+
+       return 0;
+}
+
+/****************************************************************************
+ * Name: up_destroy_gpio
+ *
+ * Description:
+ *   Destroy GPIO idx entry, release allocated priv memory.
+ *
+ * Input Parameters:
+ *   idx - GPIO index
+ *
+ * Returned Value:
+ *   OK
+ *
+ ****************************************************************************/
+int up_destroy_gpio(int32_t idx)
+{
+       struct s5j_gpio_priv *priv = (struct s5j_gpio_priv *)(s5j_gpio_all[idx]->priv);
+
+       if (priv) {
+               kmm_free(priv);
+       }
+
+       s5j_gpio_all[idx]->ops = NULL;
+       s5j_gpio_all[idx]->priv = NULL;
+
+       if (s5j_gpio_all[idx]->wdog) {
+               wd_cancel(s5j_gpio_all[idx]->wdog);
+       }
+
+       kmm_free(s5j_gpio_all[idx]);
+
+       return OK;
+}