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.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 struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip)
  29{
  30        return container_of(chip, struct pio2_card, gc);
  31}
  32
  33static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
  34{
  35        u8 reg;
  36        int retval;
  37        struct pio2_card *card = gpio_to_pio2_card(chip);
  38
  39        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
  40            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
  41                dev_err(&card->vdev->dev, "Channel not available as input\n");
  42                return 0;
  43        }
  44
  45        retval = vme_master_read(card->window, &reg, 1,
  46                                 PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
  47        if (retval < 0) {
  48                dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
  49                return 0;
  50        }
  51
  52        /*
  53         * Remember, input on channels configured as both input and output
  54         * are inverted!
  55         */
  56        if (reg & PIO2_CHANNEL_BIT[offset]) {
  57                if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
  58                        return 0;
  59
  60                return 1;
  61        }
  62
  63        if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
  64                return 1;
  65
  66        return 0;
  67}
  68
  69static void pio2_gpio_set(struct gpio_chip *chip,
  70                          unsigned int offset, int value)
  71{
  72        u8 reg;
  73        int retval;
  74        struct pio2_card *card = gpio_to_pio2_card(chip);
  75
  76        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
  77            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
  78                dev_err(&card->vdev->dev, "Channel not available as output\n");
  79                return;
  80        }
  81
  82        if (value)
  83                reg = card->bank[PIO2_CHANNEL_BANK[offset]].value |
  84                        PIO2_CHANNEL_BIT[offset];
  85        else
  86                reg = card->bank[PIO2_CHANNEL_BANK[offset]].value &
  87                        ~PIO2_CHANNEL_BIT[offset];
  88
  89        retval = vme_master_write(card->window, &reg, 1,
  90                                  PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
  91        if (retval < 0) {
  92                dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
  93                return;
  94        }
  95
  96        card->bank[PIO2_CHANNEL_BANK[offset]].value = reg;
  97}
  98
  99/* Directionality configured at board build - send appropriate response */
 100static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
 101{
 102        int data;
 103        struct pio2_card *card = gpio_to_pio2_card(chip);
 104
 105        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
 106            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
 107                dev_err(&card->vdev->dev,
 108                        "Channel directionality not configurable at runtime\n");
 109
 110                data = -EINVAL;
 111        } else {
 112                data = 0;
 113        }
 114
 115        return data;
 116}
 117
 118/* Directionality configured at board build - send appropriate response */
 119static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
 120{
 121        int data;
 122        struct pio2_card *card = gpio_to_pio2_card(chip);
 123
 124        if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
 125            (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
 126                dev_err(&card->vdev->dev,
 127                        "Channel directionality not configurable at runtime\n");
 128
 129                data = -EINVAL;
 130        } else {
 131                data = 0;
 132        }
 133
 134        return data;
 135}
 136
 137/*
 138 * We return whether this has been successful - this is used in the probe to
 139 * ensure we have a valid card.
 140 */
 141int pio2_gpio_reset(struct pio2_card *card)
 142{
 143        int retval = 0;
 144        int i, j;
 145
 146        u8 data = 0;
 147
 148        /* Zero output registers */
 149        for (i = 0; i < 4; i++) {
 150                retval = vme_master_write(card->window, &data, 1,
 151                                          PIO2_REGS_DATA[i]);
 152                if (retval < 0)
 153                        return retval;
 154                card->bank[i].value = 0;
 155        }
 156
 157        /* Set input interrupt masks */
 158        for (i = 0; i < 4; i++) {
 159                retval = vme_master_write(card->window, &data, 1,
 160                                          PIO2_REGS_INT_MASK[i * 2]);
 161                if (retval < 0)
 162                        return retval;
 163
 164                retval = vme_master_write(card->window, &data, 1,
 165                                          PIO2_REGS_INT_MASK[(i * 2) + 1]);
 166                if (retval < 0)
 167                        return retval;
 168
 169                for (j = 0; j < 8; j++)
 170                        card->bank[i].irq[j] = NONE;
 171        }
 172
 173        /* Ensure all I/O interrupts are cleared */
 174        for (i = 0; i < 4; i++) {
 175                do {
 176                        retval = vme_master_read(card->window, &data, 1,
 177                                                 PIO2_REGS_INT_STAT[i]);
 178                        if (retval < 0)
 179                                return retval;
 180                } while (data != 0);
 181        }
 182
 183        return 0;
 184}
 185
 186int pio2_gpio_init(struct pio2_card *card)
 187{
 188        int retval = 0;
 189        char *label;
 190
 191        label = kasprintf(GFP_KERNEL,
 192                          "%s@%s", driver_name, dev_name(&card->vdev->dev));
 193        if (!label)
 194                return -ENOMEM;
 195
 196        card->gc.label = label;
 197
 198        card->gc.ngpio = PIO2_NUM_CHANNELS;
 199        /* Dynamic allocation of base */
 200        card->gc.base = -1;
 201        /* Setup pointers to chip functions */
 202        card->gc.direction_input = pio2_gpio_dir_in;
 203        card->gc.direction_output = pio2_gpio_dir_out;
 204        card->gc.get = pio2_gpio_get;
 205        card->gc.set = pio2_gpio_set;
 206
 207        /* This function adds a memory mapped GPIO chip */
 208        retval = gpiochip_add(&card->gc);
 209        if (retval) {
 210                dev_err(&card->vdev->dev, "Unable to register GPIO\n");
 211                kfree(card->gc.label);
 212        }
 213
 214        return retval;
 215};
 216
 217void pio2_gpio_exit(struct pio2_card *card)
 218{
 219        const char *label = card->gc.label;
 220
 221        gpiochip_remove(&card->gc);
 222        kfree(label);
 223}
 224
 225