Merge branch 'for-rmk' of git://source.mvista.com/git/linux-davinci-2.6.git
[pandora-kernel.git] / arch / arm / mach-davinci / gpio.c
index 574cb81..b49e9d0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * TI DaVinci GPIO Support
  *
- * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2006-2007 David Brownell
  * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
  *
  * This program is free software; you can redistribute it and/or modify
 
 #include <asm/mach/irq.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
 
-int gpio_request(unsigned gpio, const char *tag)
-{
-       if (gpio >= DAVINCI_N_GPIO)
-               return -EINVAL;
+static DEFINE_SPINLOCK(gpio_lock);
 
-       if (test_and_set_bit(gpio, gpio_in_use))
-               return -EBUSY;
+struct davinci_gpio {
+       struct gpio_chip        chip;
+       struct gpio_controller  *__iomem regs;
+};
 
-       return 0;
-}
-EXPORT_SYMBOL(gpio_request);
+static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
 
-void gpio_free(unsigned gpio)
-{
-       if (gpio >= DAVINCI_N_GPIO)
-               return;
-
-       clear_bit(gpio, gpio_in_use);
-}
-EXPORT_SYMBOL(gpio_free);
 
 /* create a non-inlined version */
-static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio)
 {
        return __gpio_to_controller(gpio);
 }
 
+
+/*--------------------------------------------------------------------------*/
+
 /*
- * Assuming the pin is muxed as a gpio output, set its output value.
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
  */
-void __gpio_set(unsigned gpio, int value)
+
+static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
 {
-       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
+       struct gpio_controller *__iomem g = d->regs;
+       u32 temp;
 
-       __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
-}
-EXPORT_SYMBOL(__gpio_set);
+       spin_lock(&gpio_lock);
+       temp = __raw_readl(&g->dir);
+       temp |= (1 << offset);
+       __raw_writel(temp, &g->dir);
+       spin_unlock(&gpio_lock);
 
+       return 0;
+}
 
 /*
  * Read the pin's value (works even if it's set up as output);
@@ -75,61 +73,72 @@ EXPORT_SYMBOL(__gpio_set);
  * Note that changes are synched to the GPIO clock, so reading values back
  * right after you've set them may give old values.
  */
-int __gpio_get(unsigned gpio)
+static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
+       struct gpio_controller *__iomem g = d->regs;
 
-       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+       return (1 << offset) & __raw_readl(&g->in_data);
 }
-EXPORT_SYMBOL(__gpio_get);
 
-
-/*--------------------------------------------------------------------------*/
-
-/*
- * board setup code *MUST* set PINMUX0 and PINMUX1 as
- * needed, and enable the GPIO clock.
- */
-
-int gpio_direction_input(unsigned gpio)
+static int
+davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 {
-       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
+       struct gpio_controller *__iomem g = d->regs;
        u32 temp;
-       u32 mask;
-
-       if (!g)
-               return -EINVAL;
+       u32 mask = 1 << offset;
 
        spin_lock(&gpio_lock);
-       mask = __gpio_mask(gpio);
        temp = __raw_readl(&g->dir);
-       temp |= mask;
+       temp &= ~mask;
+       __raw_writel(mask, value ? &g->set_data : &g->clr_data);
        __raw_writel(temp, &g->dir);
        spin_unlock(&gpio_lock);
        return 0;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-int gpio_direction_output(unsigned gpio, int value)
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+static void
+davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-       struct gpio_controller *__iomem g = gpio2controller(gpio);
-       u32 temp;
-       u32 mask;
+       struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
+       struct gpio_controller *__iomem g = d->regs;
 
-       if (!g)
-               return -EINVAL;
+       __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
+}
+
+static int __init davinci_gpio_setup(void)
+{
+       int i, base;
+
+       for (i = 0, base = 0;
+                       i < ARRAY_SIZE(chips);
+                       i++, base += 32) {
+               chips[i].chip.label = "DaVinci";
+
+               chips[i].chip.direction_input = davinci_direction_in;
+               chips[i].chip.get = davinci_gpio_get;
+               chips[i].chip.direction_output = davinci_direction_out;
+               chips[i].chip.set = davinci_gpio_set;
+
+               chips[i].chip.base = base;
+               chips[i].chip.ngpio = DAVINCI_N_GPIO - base;
+               if (chips[i].chip.ngpio > 32)
+                       chips[i].chip.ngpio = 32;
+
+               chips[i].regs = gpio2controller(base);
+
+               gpiochip_add(&chips[i].chip);
+       }
 
-       spin_lock(&gpio_lock);
-       mask = __gpio_mask(gpio);
-       temp = __raw_readl(&g->dir);
-       temp &= ~mask;
-       __raw_writel(mask, value ? &g->set_data : &g->clr_data);
-       __raw_writel(temp, &g->dir);
-       spin_unlock(&gpio_lock);
        return 0;
 }
-EXPORT_SYMBOL(gpio_direction_output);
+pure_initcall(davinci_gpio_setup);
 
+/*--------------------------------------------------------------------------*/
 /*
  * We expect irqs will normally be set up as input pins, but they can also be
  * used as output pins ... which is convenient for testing.