]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: DaVinci: SOC GPIOs use gpiolib
authorDavid Brownell <dbrownell@users.sourceforge.net>
Mon, 8 Sep 2008 06:41:04 +0000 (23:41 -0700)
committerKevin Hilman <khilman@deeprootsystems.com>
Wed, 17 Sep 2008 07:31:41 +0000 (00:31 -0700)
Switch DaVinci SOC gpios over to using the new GPIO library, so it can
access GPIO expanders and other non-SOC GPIOs using the same calls.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
arch/arm/Kconfig
arch/arm/mach-davinci/gpio.c
arch/arm/mach-davinci/include/mach/gpio.h

index 70dba16689077dc0440cf12cc607f000bd5bdbdf..ea3c858d7536785a670389ce536ae3da45f04c9c 100644 (file)
@@ -515,6 +515,7 @@ config ARCH_DAVINCI
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        select HAVE_CLK
        help
          Support for TI's DaVinci platform.
index c9cb4f09b18ffd88689315a5f48c7aff6b68f45d..3ebbacdd6dba05383c0819b1caded248e209006d 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.
index ec151ccf1e8f3a951cbd8933810d80d602c0e1b9..b3a2961f0f46f7780c21a2f78eceaabc3133dffd 100644 (file)
@@ -14,6 +14,7 @@
 #define        __DAVINCI_GPIO_H
 
 #include <linux/io.h>
+#include <asm-generic/gpio.h>
 #include <mach/hardware.h>
 
 /*
  * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
  * used as gpios, not with other peripherals.
  *
- * GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation, and maybe
- * for later updates, code should write GPIO(N) or:
+ * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
+ * and maybe for later updates, code should write GPIO(N) or:
  *  - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
  *  - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
  *
  * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
  * for now, that's != GPIO(N)
+ *
+ * GPIOs can also be on external chips, numbered after the ones built-in
+ * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
  */
 #define        GPIO(X)         (X)             /* 0 <= X <= 70 */
 #define        GPIOV18(X)      (X)             /* 1.8V i/o; 0 <= X <= 53 */
@@ -67,11 +71,11 @@ __gpio_to_controller(unsigned gpio)
        void *__iomem ptr;
 
        if (gpio < 32)
-               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+               ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
        else if (gpio < 64)
-               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+               ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
        else if (gpio < DAVINCI_N_GPIO)
-               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+               ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
        else
                ptr = NULL;
        return ptr;
@@ -83,25 +87,17 @@ static inline u32 __gpio_mask(unsigned gpio)
 }
 
 /* The get/set/clear functions will inline when called with constant
- * parameters, for low-overhead bitbanging.  Illegal constant parameters
- * cause link-time errors.
+ * parameters referencing built-in GPIOs, for low-overhead bitbanging.
  *
- * Otherwise, calls with variable parameters use outlined functions.
+ * Otherwise, calls with variable parameters or referencing external
+ * GPIOs (e.g. on GPIO expander chips) use outlined functions.
  */
-extern int __error_inval_gpio(void);
-
-extern void __gpio_set(unsigned gpio, int value);
-extern int __gpio_get(unsigned gpio);
-
 static inline void gpio_set_value(unsigned gpio, int value)
 {
-       if (__builtin_constant_p(value)) {
+       if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) {
                struct gpio_controller  *__iomem g;
                u32                     mask;
 
-               if (gpio >= DAVINCI_N_GPIO)
-                       __error_inval_gpio();
-
                g = __gpio_to_controller(gpio);
                mask = __gpio_mask(gpio);
                if (value)
@@ -111,48 +107,47 @@ static inline void gpio_set_value(unsigned gpio, int value)
                return;
        }
 
-       __gpio_set(gpio, value);
+       __gpio_set_value(gpio, value);
 }
 
 /* Returns zero or nonzero; works for gpios configured as inputs OR
- * as outputs.
+ * as outputs, at least for built-in GPIOs.
  *
- * NOTE: changes in reported values are synchronized to the GPIO clock.
- * This is most easily seen after calling gpio_set_value() and then immediatly
- * gpio_get_value(), where the gpio_get_value() would return the old value
- * until the GPIO clock ticks and the new value gets latched.
+ * NOTE: for built-in GPIOs, changes in reported values are synchronized
+ * to the GPIO clock.  This is easily seen after calling gpio_set_value()
+ * and then immediately gpio_get_value(), where the gpio_get_value() will
+ * return the old value until the GPIO clock ticks and the new value gets
+ * latched.
  */
-
 static inline int gpio_get_value(unsigned gpio)
 {
-       struct gpio_controller *__iomem g;
-
-       if (!__builtin_constant_p(gpio))
-               return __gpio_get(gpio);
+       struct gpio_controller  *__iomem g;
 
-       if (gpio >= DAVINCI_N_GPIO)
-               return __error_inval_gpio();
+       if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO)
+               return __gpio_get_value(gpio);
 
        g = __gpio_to_controller(gpio);
-       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+       return __gpio_mask(gpio) & __raw_readl(&g->in_data);
 }
 
-/* powerup default direction is IN */
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
-
-#include <asm-generic/gpio.h>  /* cansleep wrappers */
-
-extern int gpio_request(unsigned gpio, const char *tag);
-extern void gpio_free(unsigned gpio);
+static inline int gpio_cansleep(unsigned gpio)
+{
+       if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO)
+               return 0;
+       else
+               return __gpio_cansleep(gpio);
+}
 
 static inline int gpio_to_irq(unsigned gpio)
 {
+       if (gpio >= DAVINCI_N_GPIO)
+               return -EINVAL;
        return DAVINCI_N_AINTC_IRQ + gpio;
 }
 
 static inline int irq_to_gpio(unsigned irq)
 {
+       /* caller guarantees gpio_to_irq() succeeded */
        return irq - DAVINCI_N_AINTC_IRQ;
 }