gpio: Move GE GPIO driver to reside within GPIO subsystem
authorMartyn Welch <martyn.welch@ge.com>
Mon, 12 Mar 2012 17:12:58 +0000 (17:12 +0000)
committerKumar Gala <galak@kernel.crashing.org>
Fri, 16 Mar 2012 16:08:08 +0000 (11:08 -0500)
The GE GPIO driver provides basic support (set direction, read/write state)
for the GPIO provided on some GE single board computers. This patch moves
the driver from the 86xx specific platform directrory to the GPIO subsystem
so that it can be used on non-86xx boards.

Signed-off-by: Martyn Welch <martyn.welch@ge.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/configs/86xx/gef_ppc9a_defconfig
arch/powerpc/configs/86xx/gef_sbc310_defconfig
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/powerpc/platforms/86xx/Makefile
arch/powerpc/platforms/86xx/gef_gpio.c [deleted file]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ge.c [new file with mode: 0644]

index d41857a5152d978827766916066edf224078f024..da731c2fe984ae67b66e30bf3b7b81eb8f42391b 100644 (file)
@@ -131,6 +131,7 @@ CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GE_FPGA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM92=y
 CONFIG_WATCHDOG=y
index 38303ec11bcd99e770dcddb119393920e7ecef6d..2149360a1e62382385c886500719b58dd4e6c0ac 100644 (file)
@@ -132,6 +132,7 @@ CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GE_FPGA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM92=y
 CONFIG_WATCHDOG=y
index 98533973d20f527234ea8967333fb04b8204814d..af2e8e1edba61e70af84fa3d7271b776e7685ba8 100644 (file)
@@ -183,6 +183,8 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GE_FPGA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM92=y
 CONFIG_WATCHDOG=y
index ac6a50fdd1d17134f2c987f19e0a74c1920e8c68..1ee6ca8e53f75b8913eb62b156839e8d36e6f519 100644 (file)
@@ -7,8 +7,7 @@ obj-$(CONFIG_SMP)               += mpc86xx_smp.o
 obj-$(CONFIG_MPC8641_HPCN)     += mpc86xx_hpcn.o
 obj-$(CONFIG_SBC8641D)         += sbc8641d.o
 obj-$(CONFIG_MPC8610_HPCD)     += mpc8610_hpcd.o
-gef-gpio-$(CONFIG_GPIOLIB)     += gef_gpio.o
-obj-$(CONFIG_GE_FPGA)  += gef_pic.o $(gef-gpio-y)
+obj-$(CONFIG_GE_FPGA)          += gef_pic.o
 obj-$(CONFIG_GEF_SBC610)       += gef_sbc610.o
 obj-$(CONFIG_GEF_SBC310)       += gef_sbc310.o
 obj-$(CONFIG_GEF_PPC9A)                += gef_ppc9a.o
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
deleted file mode 100644 (file)
index 2a70336..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Driver for GE FPGA based GPIO
- *
- * Author: Martyn Welch <martyn.welch@ge.com>
- *
- * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* TODO
- *
- * Configuration of output modes (totem-pole/open-drain)
- * Interrupt configuration - interrupts are always generated the FPGA relies on
- *     the I/O interrupt controllers mask to stop them propergating
- */
-
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#define GEF_GPIO_DIRECT                0x00
-#define GEF_GPIO_IN            0x04
-#define GEF_GPIO_OUT           0x08
-#define GEF_GPIO_TRIG          0x0C
-#define GEF_GPIO_POLAR_A       0x10
-#define GEF_GPIO_POLAR_B       0x14
-#define GEF_GPIO_INT_STAT      0x18
-#define GEF_GPIO_OVERRUN       0x1C
-#define GEF_GPIO_MODE          0x20
-
-static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
-{
-       unsigned int data;
-
-       data = ioread32be(reg);
-       /* value: 0=low; 1=high */
-       if (value & 0x1)
-               data = data | (0x1 << offset);
-       else
-               data = data & ~(0x1 << offset);
-
-       iowrite32be(data, reg);
-}
-
-
-static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
-{
-       unsigned int data;
-       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-       data = data | (0x1 << offset);
-       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
-
-       return 0;
-}
-
-static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
-{
-       unsigned int data;
-       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-       /* Set direction before switching to input */
-       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-
-       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-       data = data & ~(0x1 << offset);
-       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
-
-       return 0;
-}
-
-static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       unsigned int data;
-       int state = 0;
-       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-       data = ioread32be(mmchip->regs + GEF_GPIO_IN);
-       state = (int)((data >> offset) & 0x1);
-
-       return state;
-}
-
-static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-}
-
-static int __init gef_gpio_init(void)
-{
-       struct device_node *np;
-       int retval;
-       struct of_mm_gpio_chip *gef_gpio_chip;
-
-       for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-
-               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-               /* Allocate chip structure */
-               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-               if (!gef_gpio_chip) {
-                       pr_err("%s: Unable to allocate structure\n",
-                               np->full_name);
-                       continue;
-               }
-
-               /* Setup pointers to chip functions */
-               gef_gpio_chip->gc.of_gpio_n_cells = 2;
-               gef_gpio_chip->gc.ngpio = 19;
-               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-               gef_gpio_chip->gc.get = gef_gpio_get;
-               gef_gpio_chip->gc.set = gef_gpio_set;
-
-               /* This function adds a memory mapped GPIO chip */
-               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-               if (retval) {
-                       kfree(gef_gpio_chip);
-                       pr_err("%s: Unable to add GPIO\n", np->full_name);
-               }
-       }
-
-       for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
-
-               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-               /* Allocate chip structure */
-               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-               if (!gef_gpio_chip) {
-                       pr_err("%s: Unable to allocate structure\n",
-                               np->full_name);
-                       continue;
-               }
-
-               /* Setup pointers to chip functions */
-               gef_gpio_chip->gc.of_gpio_n_cells = 2;
-               gef_gpio_chip->gc.ngpio = 6;
-               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-               gef_gpio_chip->gc.get = gef_gpio_get;
-               gef_gpio_chip->gc.set = gef_gpio_set;
-
-               /* This function adds a memory mapped GPIO chip */
-               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-               if (retval) {
-                       kfree(gef_gpio_chip);
-                       pr_err("%s: Unable to add GPIO\n", np->full_name);
-               }
-       }
-
-       return 0;
-};
-arch_initcall(gef_gpio_init);
-
-MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
-MODULE_LICENSE("GPL");
index d0c41188d4e536b4983857de9c834913f1355c13..0409cf35adda246f944c7173b219640aa23be3c6 100644 (file)
@@ -190,6 +190,17 @@ config GPIO_VX855
          additional drivers must be enabled in order to use the
          functionality of the device.
 
+config GPIO_GE_FPGA
+       bool "GE FPGA based GPIO"
+       depends on GE_FPGA
+       help
+         Support for common GPIO functionality provided on some GE Single Board
+         Computers.
+
+         This driver provides basic support (configure as input or output, read
+         and write pin state) for GPIO implemented in a number of GE single
+         board computers.
+
 comment "I2C GPIO expanders:"
 
 config GPIO_MAX7300
index fa10df604c017badef9d8052f69e78bf84f5a24c..9a8fb54ae462df9b48b40e4e12c6eb22dcf31e97 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_CS5535)     += gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
 obj-$(CONFIG_ARCH_DAVINCI)     += gpio-davinci.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
+obj-$(CONFIG_GPIO_GE_FPGA)     += gpio-ge.o
 obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
 obj-$(CONFIG_ARCH_KS8695)      += gpio-ks8695.o
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
new file mode 100644 (file)
index 0000000..f8e6289
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Driver for GE FPGA based GPIO
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ *
+ * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/* TODO
+ *
+ * Configuration of output modes (totem-pole/open-drain)
+ * Interrupt configuration - interrupts are always generated the FPGA relies on
+ * the I/O interrupt controllers mask to stop them propergating
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#define GEF_GPIO_DIRECT                0x00
+#define GEF_GPIO_IN            0x04
+#define GEF_GPIO_OUT           0x08
+#define GEF_GPIO_TRIG          0x0C
+#define GEF_GPIO_POLAR_A       0x10
+#define GEF_GPIO_POLAR_B       0x14
+#define GEF_GPIO_INT_STAT      0x18
+#define GEF_GPIO_OVERRUN       0x1C
+#define GEF_GPIO_MODE          0x20
+
+static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+{
+       unsigned int data;
+
+       data = ioread32be(reg);
+       /* value: 0=low; 1=high */
+       if (value & 0x1)
+               data = data | (0x1 << offset);
+       else
+               data = data & ~(0x1 << offset);
+
+       iowrite32be(data, reg);
+}
+
+
+static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int data;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
+       data = data | (0x1 << offset);
+       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
+
+       return 0;
+}
+
+static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+       unsigned int data;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       /* Set direction before switching to input */
+       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
+       data = data & ~(0x1 << offset);
+       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
+
+       return 0;
+}
+
+static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int data;
+       int state = 0;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_IN);
+       state = (int)((data >> offset) & 0x1);
+
+       return state;
+}
+
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+}
+
+static int __init gef_gpio_init(void)
+{
+       struct device_node *np;
+       int retval;
+       struct of_mm_gpio_chip *gef_gpio_chip;
+
+       for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
+
+               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
+
+               /* Allocate chip structure */
+               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
+               if (!gef_gpio_chip) {
+                       pr_err("%s: Unable to allocate structure\n",
+                               np->full_name);
+                       continue;
+               }
+
+               /* Setup pointers to chip functions */
+               gef_gpio_chip->gc.of_gpio_n_cells = 2;
+               gef_gpio_chip->gc.ngpio = 19;
+               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
+               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
+               gef_gpio_chip->gc.get = gef_gpio_get;
+               gef_gpio_chip->gc.set = gef_gpio_set;
+
+               /* This function adds a memory mapped GPIO chip */
+               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
+               if (retval) {
+                       kfree(gef_gpio_chip);
+                       pr_err("%s: Unable to add GPIO\n", np->full_name);
+               }
+       }
+
+       for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
+
+               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
+
+               /* Allocate chip structure */
+               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
+               if (!gef_gpio_chip) {
+                       pr_err("%s: Unable to allocate structure\n",
+                               np->full_name);
+                       continue;
+               }
+
+               /* Setup pointers to chip functions */
+               gef_gpio_chip->gc.of_gpio_n_cells = 2;
+               gef_gpio_chip->gc.ngpio = 6;
+               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
+               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
+               gef_gpio_chip->gc.get = gef_gpio_get;
+               gef_gpio_chip->gc.set = gef_gpio_set;
+
+               /* This function adds a memory mapped GPIO chip */
+               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
+               if (retval) {
+                       kfree(gef_gpio_chip);
+                       pr_err("%s: Unable to add GPIO\n", np->full_name);
+               }
+       }
+
+       return 0;
+};
+arch_initcall(gef_gpio_init);
+
+MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
+MODULE_LICENSE("GPL");