linux/drivers/staging/iio/resolver/ad2s1200.c
<<
>>
Prefs
   1/*
   2 * ad2s1200.c simple support for the ADI Resolver to Digital Converters:
   3 * AD2S1200/1205
   4 *
   5 * Copyright (c) 2010-2010 Analog Devices Inc.
   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 */
  12#include <linux/types.h>
  13#include <linux/mutex.h>
  14#include <linux/device.h>
  15#include <linux/spi/spi.h>
  16#include <linux/slab.h>
  17#include <linux/sysfs.h>
  18#include <linux/delay.h>
  19#include <linux/gpio.h>
  20#include <linux/module.h>
  21
  22#include "../iio.h"
  23#include "../sysfs.h"
  24
  25#define DRV_NAME "ad2s1200"
  26
  27/* input pin sample and rdvel is controlled by driver */
  28#define AD2S1200_PN     2
  29
  30/* input clock on serial interface */
  31#define AD2S1200_HZ     8192000
  32/* clock period in nano second */
  33#define AD2S1200_TSCLK  (1000000000/AD2S1200_HZ)
  34
  35struct ad2s1200_state {
  36        struct mutex lock;
  37        struct spi_device *sdev;
  38        int sample;
  39        int rdvel;
  40        u8 rx[2] ____cacheline_aligned;
  41};
  42
  43static int ad2s1200_read_raw(struct iio_dev *indio_dev,
  44                           struct iio_chan_spec const *chan,
  45                           int *val,
  46                           int *val2,
  47                           long m)
  48{
  49        int ret = 0;
  50        s16 vel;
  51        struct ad2s1200_state *st = iio_priv(indio_dev);
  52
  53        mutex_lock(&st->lock);
  54        gpio_set_value(st->sample, 0);
  55        /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */
  56        udelay(1);
  57        gpio_set_value(st->sample, 1);
  58        gpio_set_value(st->rdvel, !!(chan->type == IIO_ANGL));
  59        ret = spi_read(st->sdev, st->rx, 2);
  60        if (ret < 0) {
  61                mutex_unlock(&st->lock);
  62                return ret;
  63        }
  64
  65        switch (chan->type) {
  66        case IIO_ANGL:
  67                *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
  68                break;
  69        case IIO_ANGL_VEL:
  70                vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
  71                vel = (vel << 4) >> 4;
  72                *val = vel;
  73        default:
  74                mutex_unlock(&st->lock);
  75                return -EINVAL;
  76        }
  77        /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */
  78        udelay(1);
  79        mutex_unlock(&st->lock);
  80        return IIO_VAL_INT;
  81}
  82
  83static const struct iio_chan_spec ad2s1200_channels[] = {
  84        {
  85                .type = IIO_ANGL,
  86                .indexed = 1,
  87                .channel = 0,
  88        }, {
  89                .type = IIO_ANGL_VEL,
  90                .indexed = 1,
  91                .channel = 0,
  92        }
  93};
  94
  95static const struct iio_info ad2s1200_info = {
  96        .read_raw = &ad2s1200_read_raw,
  97        .driver_module = THIS_MODULE,
  98};
  99
 100static int __devinit ad2s1200_probe(struct spi_device *spi)
 101{
 102        struct ad2s1200_state *st;
 103        struct iio_dev *indio_dev;
 104        int pn, ret = 0;
 105        unsigned short *pins = spi->dev.platform_data;
 106
 107        for (pn = 0; pn < AD2S1200_PN; pn++)
 108                if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
 109                        pr_err("%s: request gpio pin %d failed\n",
 110                                                DRV_NAME, pins[pn]);
 111                        goto error_ret;
 112                }
 113        indio_dev = iio_allocate_device(sizeof(*st));
 114        if (indio_dev == NULL) {
 115                ret = -ENOMEM;
 116                goto error_ret;
 117        }
 118        spi_set_drvdata(spi, indio_dev);
 119        st = iio_priv(indio_dev);
 120        mutex_init(&st->lock);
 121        st->sdev = spi;
 122        st->sample = pins[0];
 123        st->rdvel = pins[1];
 124
 125        indio_dev->dev.parent = &spi->dev;
 126        indio_dev->info = &ad2s1200_info;
 127        indio_dev->modes = INDIO_DIRECT_MODE;
 128        indio_dev->channels = ad2s1200_channels;
 129        indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels);
 130        indio_dev->name = spi_get_device_id(spi)->name;
 131
 132        ret = iio_device_register(indio_dev);
 133        if (ret)
 134                goto error_free_dev;
 135
 136        spi->max_speed_hz = AD2S1200_HZ;
 137        spi->mode = SPI_MODE_3;
 138        spi_setup(spi);
 139
 140        return 0;
 141
 142error_free_dev:
 143        iio_free_device(indio_dev);
 144error_ret:
 145        for (--pn; pn >= 0; pn--)
 146                gpio_free(pins[pn]);
 147        return ret;
 148}
 149
 150static int __devexit ad2s1200_remove(struct spi_device *spi)
 151{
 152        iio_device_unregister(spi_get_drvdata(spi));
 153        iio_free_device(spi_get_drvdata(spi));
 154
 155        return 0;
 156}
 157
 158static const struct spi_device_id ad2s1200_id[] = {
 159        { "ad2s1200" },
 160        { "ad2s1205" },
 161        {}
 162};
 163MODULE_DEVICE_TABLE(spi, ad2s1200_id);
 164
 165static struct spi_driver ad2s1200_driver = {
 166        .driver = {
 167                .name = DRV_NAME,
 168                .owner = THIS_MODULE,
 169        },
 170        .probe = ad2s1200_probe,
 171        .remove = __devexit_p(ad2s1200_remove),
 172        .id_table = ad2s1200_id,
 173};
 174module_spi_driver(ad2s1200_driver);
 175
 176MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>");
 177MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver");
 178MODULE_LICENSE("GPL v2");
 179
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.