Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[pandora-kernel.git] / arch / blackfin / kernel / bfin_gpio.c
index dc07ed0..170cf90 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GPIO Abstraction Layer
  *
- * Copyright 2006-2009 Analog Devices Inc.
+ * Copyright 2006-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later
  */
@@ -215,82 +215,91 @@ static void port_setup(unsigned gpio, unsigned short usage)
 }
 
 #ifdef BF537_FAMILY
-static struct {
-       unsigned short res;
-       unsigned short offset;
-} port_mux_lut[] = {
-       {.res = P_PPI0_D13, .offset = 11},
-       {.res = P_PPI0_D14, .offset = 11},
-       {.res = P_PPI0_D15, .offset = 11},
-       {.res = P_SPORT1_TFS, .offset = 11},
-       {.res = P_SPORT1_TSCLK, .offset = 11},
-       {.res = P_SPORT1_DTPRI, .offset = 11},
-       {.res = P_PPI0_D10, .offset = 10},
-       {.res = P_PPI0_D11, .offset = 10},
-       {.res = P_PPI0_D12, .offset = 10},
-       {.res = P_SPORT1_RSCLK, .offset = 10},
-       {.res = P_SPORT1_RFS, .offset = 10},
-       {.res = P_SPORT1_DRPRI, .offset = 10},
-       {.res = P_PPI0_D8, .offset = 9},
-       {.res = P_PPI0_D9, .offset = 9},
-       {.res = P_SPORT1_DRSEC, .offset = 9},
-       {.res = P_SPORT1_DTSEC, .offset = 9},
-       {.res = P_TMR2, .offset = 8},
-       {.res = P_PPI0_FS3, .offset = 8},
-       {.res = P_TMR3, .offset = 7},
-       {.res = P_SPI0_SSEL4, .offset = 7},
-       {.res = P_TMR4, .offset = 6},
-       {.res = P_SPI0_SSEL5, .offset = 6},
-       {.res = P_TMR5, .offset = 5},
-       {.res = P_SPI0_SSEL6, .offset = 5},
-       {.res = P_UART1_RX, .offset = 4},
-       {.res = P_UART1_TX, .offset = 4},
-       {.res = P_TMR6, .offset = 4},
-       {.res = P_TMR7, .offset = 4},
-       {.res = P_UART0_RX, .offset = 3},
-       {.res = P_UART0_TX, .offset = 3},
-       {.res = P_DMAR0, .offset = 3},
-       {.res = P_DMAR1, .offset = 3},
-       {.res = P_SPORT0_DTSEC, .offset = 1},
-       {.res = P_SPORT0_DRSEC, .offset = 1},
-       {.res = P_CAN0_RX, .offset = 1},
-       {.res = P_CAN0_TX, .offset = 1},
-       {.res = P_SPI0_SSEL7, .offset = 1},
-       {.res = P_SPORT0_TFS, .offset = 0},
-       {.res = P_SPORT0_DTPRI, .offset = 0},
-       {.res = P_SPI0_SSEL2, .offset = 0},
-       {.res = P_SPI0_SSEL3, .offset = 0},
+static const s8 port_mux[] = {
+       [GPIO_PF0] = 3,
+       [GPIO_PF1] = 3,
+       [GPIO_PF2] = 4,
+       [GPIO_PF3] = 4,
+       [GPIO_PF4] = 5,
+       [GPIO_PF5] = 6,
+       [GPIO_PF6] = 7,
+       [GPIO_PF7] = 8,
+       [GPIO_PF8 ... GPIO_PF15] = -1,
+       [GPIO_PG0 ... GPIO_PG7] = -1,
+       [GPIO_PG8] = 9,
+       [GPIO_PG9] = 9,
+       [GPIO_PG10] = 10,
+       [GPIO_PG11] = 10,
+       [GPIO_PG12] = 10,
+       [GPIO_PG13] = 11,
+       [GPIO_PG14] = 11,
+       [GPIO_PG15] = 11,
+       [GPIO_PH0 ... GPIO_PH15] = -1,
+       [PORT_PJ0 ... PORT_PJ3] = -1,
+       [PORT_PJ4] = 1,
+       [PORT_PJ5] = 1,
+       [PORT_PJ6 ... PORT_PJ9] = -1,
+       [PORT_PJ10] = 0,
+       [PORT_PJ11] = 0,
 };
 
-static void portmux_setup(unsigned short per)
+static int portmux_group_check(unsigned short per)
 {
-       u16 y, offset, muxreg;
+       u16 ident = P_IDENT(per);
        u16 function = P_FUNCT2MUX(per);
+       s8 offset = port_mux[ident];
+       u16 m, pmux, pfunc;
 
-       for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
-               if (port_mux_lut[y].res == per) {
-
-                       /* SET PORTMUX REG */
-
-                       offset = port_mux_lut[y].offset;
-                       muxreg = bfin_read_PORT_MUX();
+       if (offset < 0)
+               return 0;
 
-                       if (offset != 1)
-                               muxreg &= ~(1 << offset);
-                       else
-                               muxreg &= ~(3 << 1);
+       pmux = bfin_read_PORT_MUX();
+       for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
+               if (m == ident)
+                       continue;
+               if (port_mux[m] != offset)
+                       continue;
+               if (!is_reserved(peri, m, 1))
+                       continue;
 
-                       muxreg |= (function << offset);
-                       bfin_write_PORT_MUX(muxreg);
+               if (offset == 1)
+                       pfunc = (pmux >> offset) & 3;
+               else
+                       pfunc = (pmux >> offset) & 1;
+               if (pfunc != function) {
+                       pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+                               ident, function, m, pfunc);
+                       return -EINVAL;
                }
        }
+
+       return 0;
+}
+
+static void portmux_setup(unsigned short per)
+{
+       u16 ident = P_IDENT(per);
+       u16 function = P_FUNCT2MUX(per);
+       s8 offset = port_mux[ident];
+       u16 pmux;
+
+       if (offset == -1)
+               return;
+
+       pmux = bfin_read_PORT_MUX();
+       if (offset != 1)
+               pmux &= ~(1 << offset);
+       else
+               pmux &= ~(3 << 1);
+       pmux |= (function << offset);
+       bfin_write_PORT_MUX(pmux);
 }
 #elif defined(CONFIG_BF54x)
 inline void portmux_setup(unsigned short per)
 {
-       u32 pmux;
        u16 ident = P_IDENT(per);
        u16 function = P_FUNCT2MUX(per);
+       u32 pmux;
 
        pmux = gpio_array[gpio_bank(ident)]->port_mux;
 
@@ -302,20 +311,54 @@ inline void portmux_setup(unsigned short per)
 
 inline u16 get_portmux(unsigned short per)
 {
-       u32 pmux;
        u16 ident = P_IDENT(per);
-
-       pmux = gpio_array[gpio_bank(ident)]->port_mux;
-
+       u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
        return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
 }
+static int portmux_group_check(unsigned short per)
+{
+       return 0;
+}
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+static int portmux_group_check(unsigned short per)
+{
+       u16 ident = P_IDENT(per);
+       u16 function = P_FUNCT2MUX(per);
+       u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+       u16 pin, gpiopin, pfunc;
+
+       for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
+               if (offset != pmux_offset[gpio_bank(ident)][pin])
+                       continue;
+
+               gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
+               if (gpiopin == ident)
+                       continue;
+               if (!is_reserved(peri, gpiopin, 1))
+                       continue;
+
+               pfunc = *port_mux[gpio_bank(ident)];
+               pfunc = (pfunc >> offset) & 3;
+               if (pfunc != function) {
+                       pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+                               ident, function, gpiopin, pfunc);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 inline void portmux_setup(unsigned short per)
 {
-       u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
+       u16 ident = P_IDENT(per);
+       u16 function = P_FUNCT2MUX(per);
        u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+       u16 pmux;
 
        pmux = *port_mux[gpio_bank(ident)];
+       if  (((pmux >> offset) & 3) == function)
+               return;
        pmux &= ~(3 << offset);
        pmux |= (function & 3) << offset;
        *port_mux[gpio_bank(ident)] = pmux;
@@ -323,6 +366,10 @@ inline void portmux_setup(unsigned short per)
 }
 #else
 # define portmux_setup(...)  do { } while (0)
+static int portmux_group_check(unsigned short per)
+{
+       return 0;
+}
 #endif
 
 #ifndef CONFIG_BF54x
@@ -349,13 +396,13 @@ inline void portmux_setup(unsigned short per)
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
-       local_irq_save_hw(flags); \
+       flags = hard_local_irq_save(); \
        if (arg) \
                gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
        else \
                gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
        AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
+       hard_local_irq_restore(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 
@@ -371,14 +418,14 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        if (arg) \
                gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
        else \
                gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
@@ -391,11 +438,11 @@ void set_gpio_toggle(unsigned gpio)
 {
        unsigned long flags;
        if (ANOMALY_05000311 || ANOMALY_05000323)
-               local_irq_save_hw(flags);
+               flags = hard_local_irq_save();
        gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
        if (ANOMALY_05000311 || ANOMALY_05000323) {
                AWA_DUMMY_READ(toggle);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
        }
 }
 EXPORT_SYMBOL(set_gpio_toggle);
@@ -408,11 +455,11 @@ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        gpio_array[gpio_bank(gpio)]->name = arg; \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
 } \
 EXPORT_SYMBOL(set_gpiop_ ## name);
@@ -433,11 +480,11 @@ unsigned short get_gpio_ ## name(unsigned gpio) \
        unsigned long flags; \
        unsigned short ret; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
        return ret; \
 } \
@@ -460,11 +507,11 @@ unsigned short get_gpiop_ ## name(unsigned gpio) \
        unsigned long flags; \
        unsigned short ret; \
        if (ANOMALY_05000311 || ANOMALY_05000323) \
-               local_irq_save_hw(flags); \
+               flags = hard_local_irq_save(); \
        ret = (gpio_array[gpio_bank(gpio)]->name); \
        if (ANOMALY_05000311 || ANOMALY_05000323) { \
                AWA_DUMMY_READ(name); \
-               local_irq_restore_hw(flags); \
+               hard_local_irq_restore(flags); \
        } \
        return ret; \
 } \
@@ -525,14 +572,14 @@ int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        if (ctrl)
                reserve(wakeup, gpio);
        else
                unreserve(wakeup, gpio);
 
        set_gpio_maskb(gpio, ctrl);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -690,7 +737,7 @@ int peripheral_request(unsigned short per, const char *label)
 
        BUG_ON(ident >= MAX_RESOURCES);
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /* If a pin can be muxed as either GPIO or peripheral, make
         * sure it is not already a GPIO pin when we request it.
@@ -701,7 +748,7 @@ int peripheral_request(unsigned short per, const char *label)
                printk(KERN_ERR
                       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
                       __func__, ident, get_label(ident));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
 
@@ -730,18 +777,22 @@ int peripheral_request(unsigned short per, const char *label)
                        printk(KERN_ERR
                               "%s: Peripheral %d function %d is already reserved by %s !\n",
                               __func__, ident, P_FUNCT2MUX(per), get_label(ident));
-                       local_irq_restore_hw(flags);
+                       hard_local_irq_restore(flags);
                        return -EBUSY;
                }
        }
 
+       if (unlikely(portmux_group_check(per))) {
+               hard_local_irq_restore(flags);
+               return -EBUSY;
+       }
  anyway:
        reserve(peri, ident);
 
        portmux_setup(per);
        port_setup(ident, PERIPHERAL_USAGE);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        set_label(ident, label);
 
        return 0;
@@ -780,10 +831,10 @@ void peripheral_free(unsigned short per)
        if (!(per & P_DEFINED))
                return;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(peri, ident, 0))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -794,7 +845,7 @@ void peripheral_free(unsigned short per)
 
        set_label(ident, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(peripheral_free);
 
@@ -828,7 +879,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /*
         * Allow that the identical GPIO can
@@ -837,7 +888,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
         */
 
        if (cmp_label(gpio, label) == 0) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return 0;
        }
 
@@ -846,7 +897,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
                        dump_stack();
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(peri, gpio, 1))) {
@@ -855,7 +906,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
@@ -871,7 +922,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
        reserve(gpio, gpio);
        set_label(gpio, label);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        port_setup(gpio, GPIO_USAGE);
 
@@ -888,13 +939,13 @@ void bfin_gpio_free(unsigned gpio)
 
        might_sleep();
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(gpio, gpio, 0))) {
                if (system_state == SYSTEM_BOOTING)
                        dump_stack();
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -902,7 +953,7 @@ void bfin_gpio_free(unsigned gpio)
 
        set_label(gpio, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_gpio_free);
 
@@ -913,7 +964,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
 {
        unsigned long flags;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        /*
         * Allow that the identical GPIO can
@@ -922,19 +973,19 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
         */
 
        if (cmp_label(gpio, label) == 0) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return 0;
        }
 
        if (unlikely(is_reserved(special_gpio, gpio, 1))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
                       gpio, get_label(gpio));
 
                return -EBUSY;
        }
        if (unlikely(is_reserved(peri, gpio, 1))) {
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
@@ -946,7 +997,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
        reserve(peri, gpio);
 
        set_label(gpio, label);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
        port_setup(gpio, GPIO_USAGE);
 
        return 0;
@@ -959,18 +1010,18 @@ void bfin_special_gpio_free(unsigned gpio)
 
        might_sleep();
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
        unreserve(special_gpio, gpio);
        unreserve(peri, gpio);
        set_label(gpio, "free");
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_special_gpio_free);
 #endif
@@ -983,7 +1034,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
        if (check_gpio(gpio) < 0)
                return -EINVAL;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(is_reserved(peri, gpio, 1))) {
                if (system_state == SYSTEM_BOOTING)
@@ -991,7 +1042,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(is_reserved(gpio, gpio, 1)))
@@ -1002,7 +1053,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
        reserve(gpio_irq, gpio);
        set_label(gpio, label);
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        port_setup(gpio, GPIO_USAGE);
 
@@ -1016,13 +1067,13 @@ void bfin_gpio_irq_free(unsigned gpio)
        if (check_gpio(gpio) < 0)
                return;
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
                if (system_state == SYSTEM_BOOTING)
                        dump_stack();
                gpio_error(gpio);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return;
        }
 
@@ -1030,7 +1081,7 @@ void bfin_gpio_irq_free(unsigned gpio)
 
        set_label(gpio, "free");
 
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 }
 
 static inline void __bfin_gpio_direction_input(unsigned gpio)
@@ -1052,10 +1103,10 @@ int bfin_gpio_direction_input(unsigned gpio)
                return -EINVAL;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        __bfin_gpio_direction_input(gpio);
        AWA_DUMMY_READ(inen);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -1070,9 +1121,9 @@ void bfin_gpio_irq_prepare(unsigned gpio)
        port_setup(gpio, GPIO_USAGE);
 
 #ifdef CONFIG_BF54x
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
        __bfin_gpio_direction_input(gpio);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 #endif
 }
 
@@ -1094,7 +1145,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
                return -EINVAL;
        }
 
-       local_irq_save_hw(flags);
+       flags = hard_local_irq_save();
 
        gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
        gpio_set_value(gpio, value);
@@ -1105,7 +1156,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
 #endif
 
        AWA_DUMMY_READ(dir);
-       local_irq_restore_hw(flags);
+       hard_local_irq_restore(flags);
 
        return 0;
 }
@@ -1120,11 +1171,11 @@ int bfin_gpio_get_value(unsigned gpio)
 
        if (unlikely(get_gpio_edge(gpio))) {
                int ret;
-               local_irq_save_hw(flags);
+               flags = hard_local_irq_save();
                set_gpio_edge(gpio, 0);
                ret = get_gpio_data(gpio);
                set_gpio_edge(gpio, 1);
-               local_irq_restore_hw(flags);
+               hard_local_irq_restore(flags);
                return ret;
        } else
                return get_gpio_data(gpio);