]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
ARM: 6155/1: nomadik-gpio: add pin configuration API
authorRabin Vincent <rabin.vincent@stericsson.com>
Wed, 2 Jun 2010 05:06:29 +0000 (06:06 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 16 Jun 2010 21:27:35 +0000 (22:27 +0100)
Add a pin configuration API to all pin-related configuration to be
specified with a single macro and groups of pins to be configured
at one go.  Based on the PXA MFP implementation.

Cc: Alessandro Rubini <rubini@unipv.it>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/plat-nomadik/gpio.c
arch/arm/plat-nomadik/include/plat/pincfg.h [new file with mode: 0644]

index 7b7393f96a9caca3b1f5718e4ac6b70c65ef2336..465ae5bc00b1309f2c0d8c383d61f5813536376f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/irq.h>
 #include <linux/slab.h>
 
+#include <plat/pincfg.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 
@@ -95,6 +96,101 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
                writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
 }
 
+static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset)
+{
+       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+}
+
+static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
+                            pin_cfg_t cfg)
+{
+       static const char *afnames[] = {
+               [NMK_GPIO_ALT_GPIO]     = "GPIO",
+               [NMK_GPIO_ALT_A]        = "A",
+               [NMK_GPIO_ALT_B]        = "B",
+               [NMK_GPIO_ALT_C]        = "C"
+       };
+       static const char *pullnames[] = {
+               [NMK_GPIO_PULL_NONE]    = "none",
+               [NMK_GPIO_PULL_UP]      = "up",
+               [NMK_GPIO_PULL_DOWN]    = "down",
+               [3] /* illegal */       = "??"
+       };
+       static const char *slpmnames[] = {
+               [NMK_GPIO_SLPM_INPUT]           = "input",
+               [NMK_GPIO_SLPM_NOCHANGE]        = "no-change",
+       };
+
+       int pin = PIN_NUM(cfg);
+       int pull = PIN_PULL(cfg);
+       int af = PIN_ALT(cfg);
+       int slpm = PIN_SLPM(cfg);
+
+       dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n",
+               pin, afnames[af], pullnames[pull], slpmnames[slpm]);
+
+       __nmk_gpio_make_input(nmk_chip, offset);
+       __nmk_gpio_set_pull(nmk_chip, offset, pull);
+       __nmk_gpio_set_slpm(nmk_chip, offset, slpm);
+       __nmk_gpio_set_mode(nmk_chip, offset, af);
+}
+
+/**
+ * nmk_config_pin - configure a pin's mux attributes
+ * @cfg: pin confguration
+ *
+ * Configures a pin's mode (alternate function or GPIO), its pull up status,
+ * and its sleep mode based on the specified configuration.  The @cfg is
+ * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
+ * are constructed using, and can be further enhanced with, the macros in
+ * plat/pincfg.h.
+ *
+ * If a pin's mode is set to GPIO, it is configured as an input to avoid
+ * side-effects.  The gpio can be manipulated later using standard GPIO API
+ * calls.
+ */
+int nmk_config_pin(pin_cfg_t cfg)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       int gpio = PIN_NUM(cfg);
+       unsigned long flags;
+
+       nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       if (!nmk_chip)
+               return -EINVAL;
+
+       spin_lock_irqsave(&nmk_chip->lock, flags);
+       __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg);
+       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(nmk_config_pin);
+
+/**
+ * nmk_config_pins - configure several pins at once
+ * @cfgs: array of pin configurations
+ * @num: number of elments in the array
+ *
+ * Configures several pins using nmk_config_pin().  Refer to that function for
+ * further information.
+ */
+int nmk_config_pins(pin_cfg_t *cfgs, int num)
+{
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               int ret = nmk_config_pin(cfgs[i]);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(nmk_config_pins);
+
 /**
  * nmk_gpio_set_slpm() - configure the sleep mode of a pin
  * @gpio: pin number
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
new file mode 100644 (file)
index 0000000..7eed11c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ *
+ * Based on arch/arm/mach-pxa/include/mach/mfp.h:
+ *   Copyright (C) 2007 Marvell International Ltd.
+ *   eric miao <eric.miao@marvell.com>
+ */
+
+#ifndef __PLAT_PINCFG_H
+#define __PLAT_PINCFG_H
+
+/*
+ * pin configurations are represented by 32-bit integers:
+ *
+ *     bit  0.. 8 - Pin Number (512 Pins Maximum)
+ *     bit  9..10 - Alternate Function Selection
+ *     bit 11..12 - Pull up/down state
+ *     bit     13 - Sleep mode behaviour
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ *                  pull up/down = disabled
+ *                  sleep mode = input
+ *
+ * PIN_CFG        - default config with alternate function
+ * PIN_CFG_PULL           - default config with alternate function and pull up/down
+ */
+
+typedef unsigned long pin_cfg_t;
+
+#define PIN_NUM_MASK           0x1ff
+#define PIN_NUM(x)             ((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT          9
+#define PIN_ALT_MASK           (0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x)             (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO               (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A              (NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B              (NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C              (NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT         11
+#define PIN_PULL_MASK          (0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x)            (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE          (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP            (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN          (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT         13
+#define PIN_SLPM_MASK          (0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x)            (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_INPUT         (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE      (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+
+#define PIN_CFG_DEFAULT                (PIN_PULL_NONE | PIN_SLPM_INPUT)
+
+#define PIN_CFG(num, alt)              \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_PULL(num, alt, pull)   \
+       ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
+        (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
+
+extern int nmk_config_pin(pin_cfg_t cfg);
+extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
+
+#endif