linux/arch/powerpc/platforms/86xx/gef_gpio.c
<<
>>
Prefs
   1/*
   2 * Driver for GE Fanuc's FPGA based GPIO pins
   3 *
   4 * Author: Martyn Welch <martyn.welch@gefanuc.com>
   5 *
   6 * 2008 (c) GE Fanuc 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
  30#define GEF_GPIO_DIRECT         0x00
  31#define GEF_GPIO_IN             0x04
  32#define GEF_GPIO_OUT            0x08
  33#define GEF_GPIO_TRIG           0x0C
  34#define GEF_GPIO_POLAR_A        0x10
  35#define GEF_GPIO_POLAR_B        0x14
  36#define GEF_GPIO_INT_STAT       0x18
  37#define GEF_GPIO_OVERRUN        0x1C
  38#define GEF_GPIO_MODE           0x20
  39
  40static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
  41{
  42        unsigned int data;
  43
  44        data = ioread32be(reg);
  45        /* value: 0=low; 1=high */
  46        if (value & 0x1)
  47                data = data | (0x1 << offset);
  48        else
  49                data = data & ~(0x1 << offset);
  50
  51        iowrite32be(data, reg);
  52}
  53
  54
  55static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
  56{
  57        unsigned int data;
  58        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  59
  60        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  61        data = data | (0x1 << offset);
  62        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  63
  64        return 0;
  65}
  66
  67static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
  68{
  69        unsigned int data;
  70        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  71
  72        /* Set direction before switching to input */
  73        _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
  74
  75        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  76        data = data & ~(0x1 << offset);
  77        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  78
  79        return 0;
  80}
  81
  82static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
  83{
  84        unsigned int data;
  85        int state = 0;
  86        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  87
  88        data = ioread32be(mmchip->regs + GEF_GPIO_IN);
  89        state = (int)((data >> offset) & 0x1);
  90
  91        return state;
  92}
  93
  94static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  95{
  96        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  97
  98        _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
  99}
 100
 101static int __init gef_gpio_init(void)
 102{
 103        struct device_node *np;
 104        int retval;
 105        struct of_mm_gpio_chip *gef_gpio_chip;
 106
 107        for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
 108
 109                pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
 110
 111                /* Allocate chip structure */
 112                gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
 113                if (!gef_gpio_chip) {
 114                        pr_err("%s: Unable to allocate structure\n",
 115                                np->full_name);
 116                        continue;
 117                }
 118
 119                /* Setup pointers to chip functions */
 120                gef_gpio_chip->of_gc.gpio_cells = 2;
 121                gef_gpio_chip->of_gc.gc.ngpio = 19;
 122                gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
 123                gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
 124                gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
 125                gef_gpio_chip->of_gc.gc.set = gef_gpio_set;
 126
 127                /* This function adds a memory mapped GPIO chip */
 128                retval = of_mm_gpiochip_add(np, gef_gpio_chip);
 129                if (retval) {
 130                        kfree(gef_gpio_chip);
 131                        pr_err("%s: Unable to add GPIO\n", np->full_name);
 132                }
 133        }
 134
 135        for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
 136
 137                pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
 138
 139                /* Allocate chip structure */
 140                gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
 141                if (!gef_gpio_chip) {
 142                        pr_err("%s: Unable to allocate structure\n",
 143                                np->full_name);
 144                        continue;
 145                }
 146
 147                /* Setup pointers to chip functions */
 148                gef_gpio_chip->of_gc.gpio_cells = 2;
 149                gef_gpio_chip->of_gc.gc.ngpio = 6;
 150                gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
 151                gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
 152                gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
 153                gef_gpio_chip->of_gc.gc.set = gef_gpio_set;
 154
 155                /* This function adds a memory mapped GPIO chip */
 156                retval = of_mm_gpiochip_add(np, gef_gpio_chip);
 157                if (retval) {
 158                        kfree(gef_gpio_chip);
 159                        pr_err("%s: Unable to add GPIO\n", np->full_name);
 160                }
 161        }
 162
 163        return 0;
 164};
 165arch_initcall(gef_gpio_init);
 166
 167MODULE_DESCRIPTION("GE Fanuc I/O FPGA GPIO driver");
 168MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
 169MODULE_LICENSE("GPL");
 170