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 d41857a..da731c2 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 38303ec..2149360 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 9853397..af2e8e1 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 ac6a50f..1ee6ca8 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 d0c4118..0409cf3 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 fa10df6..9a8fb54 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");