linux/drivers/gpio/gpio-ge.c
<<
>>
Prefs
   1/*
   2 * Driver for GE FPGA based GPIO
   3 *
   4 * Author: Martyn Welch <martyn.welch@ge.com>
   5 *
   6 * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
   7 *
   8 * This file is licensed under the terms of the GNU General Public License
   9 * version 2.  This program is licensed "as is" without any warranty of any
  10 * kind, whether express or implied.
  11 */
  12
  13/* TODO
  14 *
  15 * Configuration of output modes (totem-pole/open-drain)
  16 * Interrupt configuration - interrupts are always generated the FPGA relies on
  17 * the I/O interrupt controllers mask to stop them propergating
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/compiler.h>
  22#include <linux/init.h>
  23#include <linux/io.h>
  24#include <linux/of.h>
  25#include <linux/of_device.h>
  26#include <linux/of_platform.h>
  27#include <linux/of_gpio.h>
  28#include <linux/gpio.h>
  29#include <linux/slab.h>
  30#include <linux/module.h>
  31
  32#define GEF_GPIO_DIRECT         0x00
  33#define GEF_GPIO_IN             0x04
  34#define GEF_GPIO_OUT            0x08
  35#define GEF_GPIO_TRIG           0x0C
  36#define GEF_GPIO_POLAR_A        0x10
  37#define GEF_GPIO_POLAR_B        0x14
  38#define GEF_GPIO_INT_STAT       0x18
  39#define GEF_GPIO_OVERRUN        0x1C
  40#define GEF_GPIO_MODE           0x20
  41
  42static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
  43{
  44        unsigned int data;
  45
  46        data = ioread32be(reg);
  47        /* value: 0=low; 1=high */
  48        if (value & 0x1)
  49                data = data | (0x1 << offset);
  50        else
  51                data = data & ~(0x1 << offset);
  52
  53        iowrite32be(data, reg);
  54}
  55
  56
  57static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
  58{
  59        unsigned int data;
  60        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  61
  62        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  63        data = data | (0x1 << offset);
  64        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  65
  66        return 0;
  67}
  68
  69static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
  70{
  71        unsigned int data;
  72        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  73
  74        /* Set direction before switching to input */
  75        _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
  76
  77        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  78        data = data & ~(0x1 << offset);
  79        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  80
  81        return 0;
  82}
  83
  84static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
  85{
  86        unsigned int data;
  87        int state = 0;
  88        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  89
  90        data = ioread32be(mmchip->regs + GEF_GPIO_IN);
  91        state = (int)((data >> offset) & 0x1);
  92
  93        return state;
  94}
  95
  96static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  97{
  98        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  99
 100        _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
 101}
 102
 103static int __init gef_gpio_init(void)
 104{
 105        struct device_node *np;
 106        int retval;
 107        struct of_mm_gpio_chip *gef_gpio_chip;
 108
 109        for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
 110
 111                pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
 112
 113                /* Allocate chip structure */
 114                gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
 115                if (!gef_gpio_chip) {
 116                        pr_err("%s: Unable to allocate structure\n",
 117                                np->full_name);
 118                        continue;
 119                }
 120
 121                /* Setup pointers to chip functions */
 122                gef_gpio_chip->gc.of_gpio_n_cells = 2;
 123                gef_gpio_chip->gc.ngpio = 19;
 124                gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
 125                gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
 126                gef_gpio_chip->gc.get = gef_gpio_get;
 127                gef_gpio_chip->gc.set = gef_gpio_set;
 128
 129                /* This function adds a memory mapped GPIO chip */
 130                retval = of_mm_gpiochip_add(np, gef_gpio_chip);
 131                if (retval) {
 132                        kfree(gef_gpio_chip);
 133                        pr_err("%s: Unable to add GPIO\n", np->full_name);
 134                }
 135        }
 136
 137        for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
 138
 139                pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
 140
 141                /* Allocate chip structure */
 142                gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
 143                if (!gef_gpio_chip) {
 144                        pr_err("%s: Unable to allocate structure\n",
 145                                np->full_name);
 146                        continue;
 147                }
 148
 149                /* Setup pointers to chip functions */
 150                gef_gpio_chip->gc.of_gpio_n_cells = 2;
 151                gef_gpio_chip->gc.ngpio = 6;
 152                gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
 153                gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
 154                gef_gpio_chip->gc.get = gef_gpio_get;
 155                gef_gpio_chip->gc.set = gef_gpio_set;
 156
 157                /* This function adds a memory mapped GPIO chip */
 158                retval = of_mm_gpiochip_add(np, gef_gpio_chip);
 159                if (retval) {
 160                        kfree(gef_gpio_chip);
 161                        pr_err("%s: Unable to add GPIO\n", np->full_name);
 162                }
 163        }
 164
 165        for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
 166
 167                pr_debug("%s: Initialising GE GPIO\n", np->full_name);
 168
 169                /* Allocate chip structure */
 170                gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
 171                if (!gef_gpio_chip) {
 172                        pr_err("%s: Unable to allocate structure\n",
 173                                np->full_name);
 174                        continue;
 175                }
 176
 177                /* Setup pointers to chip functions */
 178                gef_gpio_chip->gc.of_gpio_n_cells = 2;
 179                gef_gpio_chip->gc.ngpio = 16;
 180                gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
 181                gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
 182                gef_gpio_chip->gc.get = gef_gpio_get;
 183                gef_gpio_chip->gc.set = gef_gpio_set;
 184
 185                /* This function adds a memory mapped GPIO chip */
 186                retval = of_mm_gpiochip_add(np, gef_gpio_chip);
 187                if (retval) {
 188                        kfree(gef_gpio_chip);
 189                        pr_err("%s: Unable to add GPIO\n", np->full_name);
 190                }
 191        }
 192
 193        return 0;
 194};
 195arch_initcall(gef_gpio_init);
 196
 197MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
 198MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
 199MODULE_LICENSE("GPL");
 200
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.