linux/drivers/gpio/max7301.c
<<
>>
Prefs
   1/**
   2 * drivers/gpio/max7301.c
   3 *
   4 * Copyright (C) 2006 Juergen Beisert, Pengutronix
   5 * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are
  12 * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
  13 * details
  14 * Note:
  15 * - DIN must be stable at the rising edge of clock.
  16 * - when writing:
  17 *   - always clock in 16 clocks at once
  18 *   - at DIN: D15 first, D0 last
  19 *   - D0..D7 = databyte, D8..D14 = commandbyte
  20 *   - D15 = low -> write command
  21 * - when reading
  22 *   - always clock in 16 clocks at once
  23 *   - at DIN: D15 first, D0 last
  24 *   - D0..D7 = dummy, D8..D14 = register address
  25 *   - D15 = high -> read command
  26 *   - raise CS and assert it again
  27 *   - always clock in 16 clocks at once
  28 *   - at DOUT: D15 first, D0 last
  29 *   - D0..D7 contains the data from the first cycle
  30 *
  31 * The driver exports a standard gpiochip interface
  32 */
  33
  34#include <linux/init.h>
  35#include <linux/platform_device.h>
  36#include <linux/mutex.h>
  37#include <linux/spi/spi.h>
  38#include <linux/spi/max7301.h>
  39#include <linux/gpio.h>
  40
  41#define DRIVER_NAME "max7301"
  42
  43/*
  44 * Pin configurations, see MAX7301 datasheet page 6
  45 */
  46#define PIN_CONFIG_MASK 0x03
  47#define PIN_CONFIG_IN_PULLUP 0x03
  48#define PIN_CONFIG_IN_WO_PULLUP 0x02
  49#define PIN_CONFIG_OUT 0x01
  50
  51#define PIN_NUMBER 28
  52
  53
  54/*
  55 * Some registers must be read back to modify.
  56 * To save time we cache them here in memory
  57 */
  58struct max7301 {
  59        struct mutex    lock;
  60        u8              port_config[8]; /* field 0 is unused */
  61        u32             out_level;      /* cached output levels */
  62        struct gpio_chip chip;
  63        struct spi_device *spi;
  64};
  65
  66/**
  67 * max7301_write - Write a new register content
  68 * @spi: The SPI device
  69 * @reg: Register offset
  70 * @val: Value to write
  71 *
  72 * A write to the MAX7301 means one message with one transfer
  73 *
  74 * Returns 0 if successful or a negative value on error
  75 */
  76static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
  77{
  78        u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
  79        return spi_write(spi, (const u8 *)&word, sizeof(word));
  80}
  81
  82/**
  83 * max7301_read - Read back register content
  84 * @spi: The SPI device
  85 * @reg: Register offset
  86 *
  87 * A read from the MAX7301 means two transfers; here, one message each
  88 *
  89 * Returns positive 8 bit value from device if successful or a
  90 * negative value on error
  91 */
  92static int max7301_read(struct spi_device *spi, unsigned int reg)
  93{
  94        int ret;
  95        u16 word;
  96
  97        word = 0x8000 | (reg << 8);
  98        ret = spi_write(spi, (const u8 *)&word, sizeof(word));
  99        if (ret)
 100                return ret;
 101        /*
 102         * This relies on the fact, that a transfer with NULL tx_buf shifts out
 103         * zero bytes (=NOOP for MAX7301)
 104         */
 105        ret = spi_read(spi, (u8 *)&word, sizeof(word));
 106        if (ret)
 107                return ret;
 108        return word & 0xff;
 109}
 110
 111static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
 112{
 113        struct max7301 *ts = container_of(chip, struct max7301, chip);
 114        u8 *config;
 115        int ret;
 116
 117        /* First 4 pins are unused in the controller */
 118        offset += 4;
 119
 120        config = &ts->port_config[offset >> 2];
 121
 122        mutex_lock(&ts->lock);
 123
 124        /* Standard GPIO API doesn't support pull-ups, has to be extended.
 125         * Hard-coding no pollup for now. */
 126        *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
 127
 128        ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
 129
 130        mutex_unlock(&ts->lock);
 131
 132        return ret;
 133}
 134
 135static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
 136{
 137        if (value) {
 138                ts->out_level |= 1 << offset;
 139                return max7301_write(ts->spi, 0x20 + offset, 0x01);
 140        } else {
 141                ts->out_level &= ~(1 << offset);
 142                return max7301_write(ts->spi, 0x20 + offset, 0x00);
 143        }
 144}
 145
 146static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
 147                                    int value)
 148{
 149        struct max7301 *ts = container_of(chip, struct max7301, chip);
 150        u8 *config;
 151        int ret;
 152
 153        /* First 4 pins are unused in the controller */
 154        offset += 4;
 155
 156        config = &ts->port_config[offset >> 2];
 157
 158        mutex_lock(&ts->lock);
 159
 160        *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
 161
 162        ret = __max7301_set(ts, offset, value);
 163
 164        if (!ret)
 165                ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
 166
 167        mutex_unlock(&ts->lock);
 168
 169        return ret;
 170}
 171
 172static int max7301_get(struct gpio_chip *chip, unsigned offset)
 173{
 174        struct max7301 *ts = container_of(chip, struct max7301, chip);
 175        int config, level = -EINVAL;
 176
 177        /* First 4 pins are unused in the controller */
 178        offset += 4;
 179
 180        mutex_lock(&ts->lock);
 181
 182        config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
 183
 184        switch (config) {
 185        case 1:
 186                /* Output: return cached level */
 187                level =  !!(ts->out_level & (1 << offset));
 188                break;
 189        case 2:
 190        case 3:
 191                /* Input: read out */
 192                level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
 193        }
 194        mutex_unlock(&ts->lock);
 195
 196        return level;
 197}
 198
 199static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
 200{
 201        struct max7301 *ts = container_of(chip, struct max7301, chip);
 202
 203        /* First 4 pins are unused in the controller */
 204        offset += 4;
 205
 206        mutex_lock(&ts->lock);
 207
 208        __max7301_set(ts, offset, value);
 209
 210        mutex_unlock(&ts->lock);
 211}
 212
 213static int __devinit max7301_probe(struct spi_device *spi)
 214{
 215        struct max7301 *ts;
 216        struct max7301_platform_data *pdata;
 217        int i, ret;
 218
 219        pdata = spi->dev.platform_data;
 220        if (!pdata || !pdata->base) {
 221                dev_dbg(&spi->dev, "incorrect or missing platform data\n");
 222                return -EINVAL;
 223        }
 224
 225        /*
 226         * bits_per_word cannot be configured in platform data
 227         */
 228        spi->bits_per_word = 16;
 229
 230        ret = spi_setup(spi);
 231        if (ret < 0)
 232                return ret;
 233
 234        ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
 235        if (!ts)
 236                return -ENOMEM;
 237
 238        mutex_init(&ts->lock);
 239
 240        dev_set_drvdata(&spi->dev, ts);
 241
 242        /* Power up the chip and disable IRQ output */
 243        max7301_write(spi, 0x04, 0x01);
 244
 245        ts->spi = spi;
 246
 247        ts->chip.label = DRIVER_NAME,
 248
 249        ts->chip.direction_input = max7301_direction_input;
 250        ts->chip.get = max7301_get;
 251        ts->chip.direction_output = max7301_direction_output;
 252        ts->chip.set = max7301_set;
 253
 254        ts->chip.base = pdata->base;
 255        ts->chip.ngpio = PIN_NUMBER;
 256        ts->chip.can_sleep = 1;
 257        ts->chip.dev = &spi->dev;
 258        ts->chip.owner = THIS_MODULE;
 259
 260        /*
 261         * tristate all pins in hardware and cache the
 262         * register values for later use.
 263         */
 264        for (i = 1; i < 8; i++) {
 265                int j;
 266                /* 0xAA means input with internal pullup disabled */
 267                max7301_write(spi, 0x08 + i, 0xAA);
 268                ts->port_config[i] = 0xAA;
 269                for (j = 0; j < 4; j++) {
 270                        int offset = (i - 1) * 4 + j;
 271                        ret = max7301_direction_input(&ts->chip, offset);
 272                        if (ret)
 273                                goto exit_destroy;
 274                }
 275        }
 276
 277        ret = gpiochip_add(&ts->chip);
 278        if (ret)
 279                goto exit_destroy;
 280
 281        return ret;
 282
 283exit_destroy:
 284        dev_set_drvdata(&spi->dev, NULL);
 285        mutex_destroy(&ts->lock);
 286        kfree(ts);
 287        return ret;
 288}
 289
 290static int __devexit max7301_remove(struct spi_device *spi)
 291{
 292        struct max7301 *ts;
 293        int ret;
 294
 295        ts = dev_get_drvdata(&spi->dev);
 296        if (ts == NULL)
 297                return -ENODEV;
 298
 299        dev_set_drvdata(&spi->dev, NULL);
 300
 301        /* Power down the chip and disable IRQ output */
 302        max7301_write(spi, 0x04, 0x00);
 303
 304        ret = gpiochip_remove(&ts->chip);
 305        if (!ret) {
 306                mutex_destroy(&ts->lock);
 307                kfree(ts);
 308        } else
 309                dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
 310                        ret);
 311
 312        return ret;
 313}
 314
 315static struct spi_driver max7301_driver = {
 316        .driver = {
 317                .name           = DRIVER_NAME,
 318                .owner          = THIS_MODULE,
 319        },
 320        .probe          = max7301_probe,
 321        .remove         = __devexit_p(max7301_remove),
 322};
 323
 324static int __init max7301_init(void)
 325{
 326        return spi_register_driver(&max7301_driver);
 327}
 328/* register after spi postcore initcall and before
 329 * subsys initcalls that may rely on these GPIOs
 330 */
 331subsys_initcall(max7301_init);
 332
 333static void __exit max7301_exit(void)
 334{
 335        spi_unregister_driver(&max7301_driver);
 336}
 337module_exit(max7301_exit);
 338
 339MODULE_AUTHOR("Juergen Beisert");
 340MODULE_LICENSE("GPL v2");
 341MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
 342MODULE_ALIAS("spi:" DRIVER_NAME);
 343
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.