linux/drivers/staging/vme/devices/vme_pio2_gpio.c
<<
>>
Prefs
   1/*
   2 * GE PIO2 GPIO Driver
   3 *
   4 * Author: Martyn Welch <martyn.welch@ge.com>
   5 * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
   6 *
   7 * This program is free software; you can redistribute  it and/or modify it
   8 * under  the terms of  the GNU General  Public License as published by the
   9 * Free Software Foundation;  either version 2 of the  License, or (at your
  10 * option) any later version.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/types.h>
  15#include <linux/kernel.h>
  16#include <linux/errno.h>
  17#include <linux/device.h>
  18#include <linux/platform_device.h>
  19#include <linux/ctype.h>
  20#include <linux/gpio/driver.h>
  21#include <linux/slab.h>
  22#include <linux/vme.h>
  23
  24#include "vme_pio2.h"
  25
  26static const char driver_name[] = "pio2_gpio";
  27
  28static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
  29{
  30        u8 reg;
  31        int retval;
  32        struct pio2_card *card = gpiochip_get_data(chip);
  33
  34        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
  35            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
  36                dev_err(&card->vdev->dev, "Channel not available as input\n");
  37                return 0;
  38        }
  39
  40        retval = vme_master_read(card->window, &reg, 1,
  41                                 PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
  42        if (retval < 0) {
  43                dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
  44                return 0;
  45        }
  46
  47        /*
  48         * Remember, input on channels configured as both input and output
  49         * are inverted!
  50         */
  51        if (reg & PIO2_CHANNEL_BIT[offset]) {
  52                if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
  53                        return 0;
  54
  55                return 1;
  56        }
  57
  58        if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
  59                return 1;
  60
  61        return 0;
  62}
  63
  64static void pio2_gpio_set(struct gpio_chip *chip,
  65                          unsigned int offset, int value)
  66{
  67        u8 reg;
  68        int retval;
  69        struct pio2_card *card = gpiochip_get_data(chip);
  70
  71        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
  72            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
  73                dev_err(&card->vdev->dev, "Channel not available as output\n");
  74                return;
  75        }
  76
  77        if (value)
  78                reg = card->bank[PIO2_CHANNEL_BANK[offset]].value |
  79                        PIO2_CHANNEL_BIT[offset];
  80        else
  81                reg = card->bank[PIO2_CHANNEL_BANK[offset]].value &
  82                        ~PIO2_CHANNEL_BIT[offset];
  83
  84        retval = vme_master_write(card->window, &reg, 1,
  85                                  PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
  86        if (retval < 0) {
  87                dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
  88                return;
  89        }
  90
  91        card->bank[PIO2_CHANNEL_BANK[offset]].value = reg;
  92}
  93
  94/* Directionality configured at board build - send appropriate response */
  95static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
  96{
  97        int data;
  98        struct pio2_card *card = gpiochip_get_data(chip);
  99
 100        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
 101            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
 102                dev_err(&card->vdev->dev,
 103                        "Channel directionality not configurable at runtime\n");
 104
 105                data = -EINVAL;
 106        } else {
 107                data = 0;
 108        }
 109
 110        return data;
 111}
 112
 113/* Directionality configured at board build - send appropriate response */
 114static int pio2_gpio_dir_out(struct gpio_chip *chip,
 115                             unsigned int offset, int value)
 116{
 117        int data;
 118        struct pio2_card *card = gpiochip_get_data(chip);
 119
 120        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
 121            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
 122                dev_err(&card->vdev->dev,
 123                        "Channel directionality not configurable at runtime\n");
 124
 125                data = -EINVAL;
 126        } else {
 127                data = 0;
 128        }
 129
 130        return data;
 131}
 132
 133/*
 134 * We return whether this has been successful - this is used in the probe to
 135 * ensure we have a valid card.
 136 */
 137int pio2_gpio_reset(struct pio2_card *card)
 138{
 139        int retval = 0;
 140        int i, j;
 141
 142        u8 data = 0;
 143
 144        /* Zero output registers */
 145        for (i = 0; i < 4; i++) {
 146                retval = vme_master_write(card->window, &data, 1,
 147                                          PIO2_REGS_DATA[i]);
 148                if (retval < 0)
 149                        return retval;
 150                card->bank[i].value = 0;
 151        }
 152
 153        /* Set input interrupt masks */
 154        for (i = 0; i < 4; i++) {
 155                retval = vme_master_write(card->window, &data, 1,
 156                                          PIO2_REGS_INT_MASK[i * 2]);
 157                if (retval < 0)
 158                        return retval;
 159
 160                retval = vme_master_write(card->window, &data, 1,
 161                                          PIO2_REGS_INT_MASK[(i * 2) + 1]);
 162                if (retval < 0)
 163                        return retval;
 164
 165                for (j = 0; j < 8; j++)
 166                        card->bank[i].irq[j] = NONE;
 167        }
 168
 169        /* Ensure all I/O interrupts are cleared */
 170        for (i = 0; i < 4; i++) {
 171                do {
 172                        retval = vme_master_read(card->window, &data, 1,
 173                                                 PIO2_REGS_INT_STAT[i]);
 174                        if (retval < 0)
 175                                return retval;
 176                } while (data != 0);
 177        }
 178
 179        return 0;
 180}
 181
 182int pio2_gpio_init(struct pio2_card *card)
 183{
 184        int retval = 0;
 185        char *label;
 186
 187        label = kasprintf(GFP_KERNEL,
 188                          "%s@%s", driver_name, dev_name(&card->vdev->dev));
 189        if (!label)
 190                return -ENOMEM;
 191
 192        card->gc.label = label;
 193
 194        card->gc.ngpio = PIO2_NUM_CHANNELS;
 195        /* Dynamic allocation of base */
 196        card->gc.base = -1;
 197        /* Setup pointers to chip functions */
 198        card->gc.direction_input = pio2_gpio_dir_in;
 199        card->gc.direction_output = pio2_gpio_dir_out;
 200        card->gc.get = pio2_gpio_get;
 201        card->gc.set = pio2_gpio_set;
 202
 203        /* This function adds a memory mapped GPIO chip */
 204        retval = gpiochip_add_data(&card->gc, card);
 205        if (retval) {
 206                dev_err(&card->vdev->dev, "Unable to register GPIO\n");
 207                kfree(card->gc.label);
 208        }
 209
 210        return retval;
 211};
 212
 213void pio2_gpio_exit(struct pio2_card *card)
 214{
 215        const char *label = card->gc.label;
 216
 217        gpiochip_remove(&card->gc);
 218        kfree(label);
 219}
 220
 221