[ARM] orion: convert gpio to use gpiolib
authorErik Benada <erikbenada@yahoo.ca>
Fri, 29 May 2009 00:08:55 +0000 (17:08 -0700)
committerNicolas Pitre <nico@cam.org>
Mon, 8 Jun 2009 17:04:57 +0000 (13:04 -0400)
Signed-off-by: Erik Benada <erikbenada@yahoo.ca>
[ nico: fix locking, additional cleanups ]

Signed-off-by: Nicolas Pitre <nico@marvell.com>
arch/arm/Kconfig
arch/arm/mach-kirkwood/mpp.c
arch/arm/mach-mv78xx0/irq.c
arch/arm/mach-orion5x/mpp.c
arch/arm/plat-orion/gpio.c
arch/arm/plat-orion/include/plat/gpio.h

index 9d02cdb15b23dc6d4524cf61db4153c810639580..c6225ead7bffe3b45053cf27a0bbdd49e95fb5a3 100644 (file)
@@ -398,6 +398,7 @@ config ARCH_KIRKWOOD
        select CPU_FEROCEON
        select PCI
        select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select PLAT_ORION
@@ -441,6 +442,7 @@ config ARCH_MV78XX0
        select CPU_FEROCEON
        select PCI
        select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select PLAT_ORION
@@ -465,6 +467,7 @@ config ARCH_ORION5X
        select CPU_FEROCEON
        select PCI
        select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select PLAT_ORION
index 63c44934391ac5c68e62350004bbcfa129d49eda..a5900f64e38c112e7fb195ea2cdca7281cc64af7 100644 (file)
@@ -48,6 +48,9 @@ void __init kirkwood_mpp_conf(unsigned int *mpp_list)
        if (!variant_mask)
                return;
 
+       /* Initialize gpiolib. */
+       orion_gpio_init();
+
        printk(KERN_DEBUG "initial MPP regs:");
        for (i = 0; i < MPP_NR_REGS; i++) {
                mpp_ctrl[i] = readl(MPP_CTRL(i));
index f289b0ea7dcf8005a1f8cbab8d5fdb0744ec1667..22b4ff893b3c6c04d13fc680f39ab43ae7ac2e3e 100644 (file)
@@ -28,6 +28,9 @@ void __init mv78xx0_init_irq(void)
 {
        int i;
 
+       /* Initialize gpiolib. */
+       orion_gpio_init();
+
        orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
        orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
        orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
index e23a3f91d6c61b777356187df9aceddfc1dae160..bc4c3b9aaf83346fc054b5cb23eb19287b3e2fc0 100644 (file)
@@ -124,6 +124,9 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode)
        u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL);
        u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL);
 
+       /* Initialize gpiolib. */
+       orion_gpio_init();
+
        while (mode->mpp >= 0) {
                u32 *reg;
                int num_type;
index 32eb9e33bebbe448d47d7500b53e79dfe81d46a8..e814803d474187e384e893c62f5d229fe50f32bb 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 static DEFINE_SPINLOCK(gpio_lock);
-static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
 static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
 static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
 
@@ -46,82 +45,54 @@ static void __set_level(unsigned pin, int high)
        writel(u, GPIO_OUT(pin));
 }
 
-
-/*
- * GENERIC_GPIO primitives.
- */
-int gpio_direction_input(unsigned pin)
+static inline void __set_blinking(unsigned pin, int blink)
 {
-       unsigned long flags;
-
-       if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) {
-               pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&gpio_lock, flags);
-
-       /*
-        * Some callers might not have used gpio_request(),
-        * so flag this pin as requested now.
-        */
-       if (gpio_label[pin] == NULL)
-               gpio_label[pin] = "?";
+       u32 u;
 
-       /*
-        * Configure GPIO direction.
-        */
-       __set_direction(pin, 1);
+       u = readl(GPIO_BLINK_EN(pin));
+       if (blink)
+               u |= 1 << (pin & 31);
+       else
+               u &= ~(1 << (pin & 31));
+       writel(u, GPIO_BLINK_EN(pin));
+}
 
-       spin_unlock_irqrestore(&gpio_lock, flags);
+static inline int orion_gpio_is_valid(unsigned pin, int mode)
+{
+       if (pin < GPIO_MAX) {
+               if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
+                       goto err_out;
+               if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
+                       goto err_out;
+               return true;
+       }
 
-       return 0;
+err_out:
+       pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+       return false;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-int gpio_direction_output(unsigned pin, int value)
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
        unsigned long flags;
-       u32 u;
 
-       if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) {
-               pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+       if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK))
                return -EINVAL;
-       }
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       /*
-        * Some callers might not have used gpio_request(),
-        * so flag this pin as requested now.
-        */
-       if (gpio_label[pin] == NULL)
-               gpio_label[pin] = "?";
-
-       /*
-        * Disable blinking.
-        */
-       u = readl(GPIO_BLINK_EN(pin));
-       u &= ~(1 << (pin & 31));
-       writel(u, GPIO_BLINK_EN(pin));
-
-       /*
-        * Configure GPIO output value.
-        */
-       __set_level(pin, value);
-
-       /*
-        * Configure GPIO direction.
-        */
-       __set_direction(pin, 0);
+       /* Configure GPIO direction. */
+       __set_direction(pin, 1);
 
        spin_unlock_irqrestore(&gpio_lock, flags);
 
        return 0;
 }
-EXPORT_SYMBOL(gpio_direction_output);
 
-int gpio_get_value(unsigned pin)
+static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin)
 {
        int val;
 
@@ -132,83 +103,75 @@ int gpio_get_value(unsigned pin)
 
        return (val >> (pin & 31)) & 1;
 }
-EXPORT_SYMBOL(gpio_get_value);
 
-void gpio_set_value(unsigned pin, int value)
+static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+       int value)
 {
        unsigned long flags;
-       u32 u;
+
+       if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+               return -EINVAL;
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       /*
-        * Disable blinking.
-        */
-       u = readl(GPIO_BLINK_EN(pin));
-       u &= ~(1 << (pin & 31));
-       writel(u, GPIO_BLINK_EN(pin));
+       /* Disable blinking. */
+       __set_blinking(pin, 0);
 
-       /*
-        * Configure GPIO output value.
-        */
+       /* Configure GPIO output value. */
        __set_level(pin, value);
 
+       /* Configure GPIO direction. */
+       __set_direction(pin, 0);
+
        spin_unlock_irqrestore(&gpio_lock, flags);
+
+       return 0;
 }
-EXPORT_SYMBOL(gpio_set_value);
 
-int gpio_request(unsigned pin, const char *label)
+static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin,
+       int value)
 {
        unsigned long flags;
-       int ret;
-
-       if (pin >= GPIO_MAX ||
-           !(test_bit(pin, gpio_valid_input) ||
-             test_bit(pin, gpio_valid_output))) {
-               pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-               return -EINVAL;
-       }
 
        spin_lock_irqsave(&gpio_lock, flags);
-       if (gpio_label[pin] == NULL) {
-               gpio_label[pin] = label ? label : "?";
-               ret = 0;
-       } else {
-               pr_debug("%s: GPIO %d already used as %s\n",
-                        __func__, pin, gpio_label[pin]);
-               ret = -EBUSY;
-       }
-       spin_unlock_irqrestore(&gpio_lock, flags);
 
-       return ret;
+       /* Configure GPIO output value. */
+       __set_level(pin, value);
+
+       spin_unlock_irqrestore(&gpio_lock, flags);
 }
-EXPORT_SYMBOL(gpio_request);
 
-void gpio_free(unsigned pin)
+static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
-       if (pin >= GPIO_MAX ||
-           !(test_bit(pin, gpio_valid_input) ||
-             test_bit(pin, gpio_valid_output))) {
-               pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-               return;
-       }
-
-       if (gpio_label[pin] == NULL)
-               pr_warning("%s: GPIO %d already freed\n", __func__, pin);
-       else
-               gpio_label[pin] = NULL;
+       if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) ||
+           orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+               return 0;
+       return -EINVAL;
 }
-EXPORT_SYMBOL(gpio_free);
 
+static struct gpio_chip orion_gpiochip = {
+       .label                  = "orion_gpio",
+       .direction_input        = orion_gpio_direction_input,
+       .get                    = orion_gpio_get_value,
+       .direction_output       = orion_gpio_direction_output,
+       .set                    = orion_gpio_set_value,
+       .request                = orion_gpio_request,
+       .base                   = 0,
+       .ngpio                  = GPIO_MAX,
+       .can_sleep              = 0,
+};
+
+void __init orion_gpio_init(void)
+{
+       gpiochip_add(&orion_gpiochip);
+}
 
 /*
  * Orion-specific GPIO API extensions.
  */
 void __init orion_gpio_set_unused(unsigned pin)
 {
-       /*
-        * Configure as output, drive low.
-        */
+       /* Configure as output, drive low. */
        __set_level(pin, 0);
        __set_direction(pin, 0);
 }
@@ -230,21 +193,14 @@ void __init orion_gpio_set_valid(unsigned pin, int mode)
 void orion_gpio_set_blink(unsigned pin, int blink)
 {
        unsigned long flags;
-       u32 u;
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       /*
-        * Set output value to zero.
-        */
+       /* Set output value to zero. */
        __set_level(pin, 0);
 
-       u = readl(GPIO_BLINK_EN(pin));
-       if (blink)
-               u |= 1 << (pin & 31);
-       else
-               u &= ~(1 << (pin & 31));
-       writel(u, GPIO_BLINK_EN(pin));
+       /* Set blinking. */
+       __set_blinking(pin, blink);
 
        spin_unlock_irqrestore(&gpio_lock, flags);
 }
@@ -368,7 +324,7 @@ static int gpio_irq_set_type(u32 irq, u32 type)
 }
 
 struct irq_chip orion_gpio_irq_chip = {
-       .name           = "orion_gpio",
+       .name           = "orion_gpio_irq",
        .ack            = gpio_irq_ack,
        .mask           = gpio_irq_mask,
        .unmask         = gpio_irq_unmask,
index 33f6c6aec1858374e967a88f19fd1461b7a08a39..9646a94ed3d06aa1937f8d9889d11248777ebec3 100644 (file)
 /*
  * GENERIC_GPIO primitives.
  */
-int gpio_request(unsigned pin, const char *label);
-void gpio_free(unsigned pin);
-int gpio_direction_input(unsigned pin);
-int gpio_direction_output(unsigned pin, int value);
-int gpio_get_value(unsigned pin);
-void gpio_set_value(unsigned pin, int value);
+#define gpio_get_value  __gpio_get_value
+#define gpio_set_value  __gpio_set_value
+#define gpio_cansleep   __gpio_cansleep
 
 /*
  * Orion-specific GPIO API extensions.
@@ -27,11 +24,13 @@ void gpio_set_value(unsigned pin, int value);
 void orion_gpio_set_unused(unsigned pin);
 void orion_gpio_set_blink(unsigned pin, int blink);
 
-#define GPIO_BIDI_OK           (1 << 0)
-#define GPIO_INPUT_OK          (1 << 1)
-#define GPIO_OUTPUT_OK         (1 << 2)
+#define GPIO_INPUT_OK          (1 << 0)
+#define GPIO_OUTPUT_OK         (1 << 1)
 void orion_gpio_set_valid(unsigned pin, int mode);
 
+/* Initialize gpiolib. */
+void __init orion_gpio_init(void);
+
 /*
  * GPIO interrupt handling.
  */