]> err.no Git - linux-2.6/blobdiff - arch/arm/mach-ep93xx/core.c
[ARM] 4668/1: ep93xx: implement new GPIO API
[linux-2.6] / arch / arm / mach-ep93xx / core.c
index 94bba0b87e3679f79cd055f6f975a1a3d413c096..8a734066137737349c6da15adbc8a06524cdb53d 100644 (file)
@@ -116,7 +116,7 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ep93xx_timer_irq = {
        .name           = "ep93xx timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ep93xx_timer_interrupt,
 };
 
@@ -152,7 +152,8 @@ struct sys_timer ep93xx_timer = {
 /*************************************************************************
  * GPIO handling for EP93xx
  *************************************************************************/
-static unsigned char gpio_int_enable[3];
+static unsigned char gpio_int_unmasked[3];
+static unsigned char gpio_int_enabled[3];
 static unsigned char gpio_int_type1[3];
 static unsigned char gpio_int_type2[3];
 
@@ -162,17 +163,17 @@ static void update_gpio_int_params(int abf)
                __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
                __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
                __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
-               __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
+               __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
        } else if (abf == 1) {
                __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
                __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
                __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
-               __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
+               __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
        } else if (abf == 2) {
                __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
                __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
                __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
-               __raw_writeb(gpio_int_enable[2], EP93XX_GPIO_F_INT_ENABLE);
+               __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
        } else {
                BUG();
        }
@@ -187,7 +188,7 @@ static unsigned char data_direction_register_offset[8] = {
        0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44,
 };
 
-void gpio_line_config(int line, int direction)
+static void ep93xx_gpio_set_direction(unsigned line, int direction)
 {
        unsigned int data_direction_register;
        unsigned long flags;
@@ -200,11 +201,11 @@ void gpio_line_config(int line, int direction)
        if (direction == GPIO_OUT) {
                if (line >= 0 && line < 16) {
                        /* Port A/B.  */
-                       gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
+                       gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
                        update_gpio_int_params(line >> 3);
                } else if (line >= 40 && line < 48) {
                        /* Port F.  */
-                       gpio_int_enable[2] &= ~(1 << (line & 7));
+                       gpio_int_unmasked[2] &= ~(1 << (line & 7));
                        update_gpio_int_params(2);
                }
 
@@ -218,39 +219,64 @@ void gpio_line_config(int line, int direction)
        }
        local_irq_restore(flags);
 }
+
+void __deprecated gpio_line_config(int line, int direction)
+{
+       ep93xx_gpio_set_direction(line, direction);
+}
 EXPORT_SYMBOL(gpio_line_config);
 
-int gpio_line_get(int line)
+int gpio_direction_input(unsigned gpio)
+{
+       if (gpio > EP93XX_GPIO_LINE_H(7))
+               return -EINVAL;
+
+       ep93xx_gpio_set_direction(gpio, GPIO_IN);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       if (gpio > EP93XX_GPIO_LINE_H(7))
+               return -EINVAL;
+
+       gpio_set_value(gpio, value);
+       ep93xx_gpio_set_direction(gpio, GPIO_OUT);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+int gpio_get_value(unsigned gpio)
 {
        unsigned int data_register;
 
-       data_register = EP93XX_GPIO_REG(data_register_offset[line >> 3]);
+       data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
 
-       return !!(__raw_readb(data_register) & (1 << (line & 7)));
+       return !!(__raw_readb(data_register) & (1 << (gpio & 7)));
 }
-EXPORT_SYMBOL(gpio_line_get);
+EXPORT_SYMBOL(gpio_get_value);
 
-void gpio_line_set(int line, int value)
+void gpio_set_value(unsigned gpio, int value)
 {
        unsigned int data_register;
        unsigned long flags;
        unsigned char v;
 
-       data_register = EP93XX_GPIO_REG(data_register_offset[line >> 3]);
+       data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
 
        local_irq_save(flags);
-       if (value == EP93XX_GPIO_HIGH) {
-               v = __raw_readb(data_register);
-               v |= 1 << (line & 7);
-               __raw_writeb(v, data_register);
-       } else if (value == EP93XX_GPIO_LOW) {
-               v = __raw_readb(data_register);
-               v &= ~(1 << (line & 7));
-               __raw_writeb(v, data_register);
-       }
+       v = __raw_readb(data_register);
+       if (value)
+               v |= 1 << (gpio & 7);
+       else
+               v &= ~(1 << (gpio & 7));
+       __raw_writeb(v, data_register);
        local_irq_restore(flags);
 }
-EXPORT_SYMBOL(gpio_line_set);
+EXPORT_SYMBOL(gpio_set_value);
 
 
 /*************************************************************************
@@ -290,7 +316,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] &= ~(1 << (line & 7));
+       gpio_int_unmasked[port] &= ~(1 << (line & 7));
        update_gpio_int_params(port);
 
        if (port == 0) {
@@ -307,7 +333,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] &= ~(1 << (line & 7));
+       gpio_int_unmasked[port] &= ~(1 << (line & 7));
        update_gpio_int_params(port);
 }
 
@@ -316,7 +342,7 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
        int line = irq - IRQ_EP93XX_GPIO(0);
        int port = line >> 3;
 
-       gpio_int_enable[port] |= 1 << (line & 7);
+       gpio_int_unmasked[port] |= 1 << (line & 7);
        update_gpio_int_params(port);
 }
 
@@ -333,26 +359,32 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
 
        line = irq - IRQ_EP93XX_GPIO(0);
        if (line >= 0 && line < 16) {
-               gpio_line_config(line, GPIO_IN);
+               ep93xx_gpio_set_direction(line, GPIO_IN);
        } else {
-               gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
+               ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN);
        }
 
        port = line >> 3;
        line &= 7;
 
        if (type & IRQT_RISING) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] |= 1 << line;
                gpio_int_type2[port] |= 1 << line;
        } else if (type & IRQT_FALLING) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] |= 1 << line;
                gpio_int_type2[port] &= ~(1 << line);
        } else if (type & IRQT_HIGH) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] &= ~(1 << line);
                gpio_int_type2[port] |= 1 << line;
        } else if (type & IRQT_LOW) {
+               gpio_int_enabled[port] |= 1 << line;
                gpio_int_type1[port] &= ~(1 << line);
                gpio_int_type2[port] &= ~(1 << line);
+       } else {
+               gpio_int_enabled[port] &= ~(1 << line);
        }
        update_gpio_int_params(port);