summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/gpio.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-10-09 21:33:05 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-10-09 21:33:05 +0100
commitc97f68145e8067b3ac4b126a6faebf90f9ffc302 (patch)
treeeb2060681552a00e9efa98224b95f69a3dc84390 /arch/arm/mach-davinci/gpio.c
parentb1add0480a95b6ceaece5caf6c50614771eae9b2 (diff)
parent7bff3c4ce44ea48f50dc47a5994454984bd08c59 (diff)
Merge branch 'for-rmk' of git://source.mvista.com/git/linux-davinci-2.6.git
Merge branch 'davinci' into devel
Diffstat (limited to 'arch/arm/mach-davinci/gpio.c')
-rw-r--r--arch/arm/mach-davinci/gpio.c133
1 files changed, 71 insertions, 62 deletions
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
index 574cb810a50..b49e9d092aa 100644
--- a/arch/arm/mach-davinci/gpio.c
+++ b/arch/arm/mach-davinci/gpio.c
@@ -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
@@ -26,47 +26,45 @@
#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.