123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /*
- * 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);
- }
- }
- for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
- pr_debug("%s: Initialising GE 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 = 16;
- 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");
|