Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / gpio / gpio-ge.c
diff --git a/kernel/drivers/gpio/gpio-ge.c b/kernel/drivers/gpio/gpio-ge.c
new file mode 100644 (file)
index 0000000..f9ac3f3
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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/io.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/basic_mmio_gpio.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 const struct of_device_id gef_gpio_ids[] = {
+       {
+               .compatible     = "gef,sbc610-gpio",
+               .data           = (void *)19,
+       }, {
+               .compatible     = "gef,sbc310-gpio",
+               .data           = (void *)6,
+       }, {
+               .compatible     = "ge,imp3a-gpio",
+               .data           = (void *)16,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, gef_gpio_ids);
+
+static int __init gef_gpio_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+               of_match_device(gef_gpio_ids, &pdev->dev);
+       struct bgpio_chip *bgc;
+       void __iomem *regs;
+       int ret;
+
+       bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
+       if (!bgc)
+               return -ENOMEM;
+
+       regs = of_iomap(pdev->dev.of_node, 0);
+       if (!regs)
+               return -ENOMEM;
+
+       ret = bgpio_init(bgc, &pdev->dev, 4, regs + GEF_GPIO_IN,
+                        regs + GEF_GPIO_OUT, NULL, NULL,
+                        regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+       if (ret) {
+               dev_err(&pdev->dev, "bgpio_init failed\n");
+               goto err0;
+       }
+
+       /* Setup pointers to chip functions */
+       bgc->gc.label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
+                                    GFP_KERNEL);
+       if (!bgc->gc.label) {
+               ret = -ENOMEM;
+               goto err0;
+       }
+
+       bgc->gc.base = -1;
+       bgc->gc.ngpio = (u16)(uintptr_t)of_id->data;
+       bgc->gc.of_gpio_n_cells = 2;
+       bgc->gc.of_node = pdev->dev.of_node;
+
+       /* This function adds a memory mapped GPIO chip */
+       ret = gpiochip_add(&bgc->gc);
+       if (ret)
+               goto err0;
+
+       return 0;
+err0:
+       iounmap(regs);
+       pr_err("%s: GPIO chip registration failed\n",
+                       pdev->dev.of_node->full_name);
+       return ret;
+};
+
+static struct platform_driver gef_gpio_driver = {
+       .driver = {
+               .name           = "gef-gpio",
+               .of_match_table = gef_gpio_ids,
+       },
+};
+module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
+
+MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
+MODULE_LICENSE("GPL");