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 <linux/iio/iio.h>
  23#include <linux/iio/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                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  89        }, {
  90                .type = IIO_ANGL_VEL,
  91                .indexed = 1,
  92                .channel = 0,
  93                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  94        }
  95};
  96
  97static const struct iio_info ad2s1200_info = {
  98        .read_raw = &ad2s1200_read_raw,
  99        .driver_module = THIS_MODULE,
 100};
 101
 102static int ad2s1200_probe(struct spi_device *spi)
 103{
 104        struct ad2s1200_state *st;
 105        struct iio_dev *indio_dev;
 106        int pn, ret = 0;
 107        unsigned short *pins = spi->dev.platform_data;
 108
 109        for (pn = 0; pn < AD2S1200_PN; pn++)
 110                if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
 111                        pr_err("%s: request gpio pin %d failed\n",
 112                                                DRV_NAME, pins[pn]);
 113                        goto error_ret;
 114                }
 115        indio_dev = iio_device_alloc(sizeof(*st));
 116        if (indio_dev == NULL) {
 117                ret = -ENOMEM;
 118                goto error_ret;
 119        }
 120        spi_set_drvdata(spi, indio_dev);
 121        st = iio_priv(indio_dev);
 122        mutex_init(&st->lock);
 123        st->sdev = spi;
 124        st->sample = pins[0];
 125        st->rdvel = pins[1];
 126
 127        indio_dev->dev.parent = &spi->dev;
 128        indio_dev->info = &ad2s1200_info;
 129        indio_dev->modes = INDIO_DIRECT_MODE;
 130        indio_dev->channels = ad2s1200_channels;
 131        indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels);
 132        indio_dev->name = spi_get_device_id(spi)->name;
 133
 134        ret = iio_device_register(indio_dev);
 135        if (ret)
 136                goto error_free_dev;
 137
 138        spi->max_speed_hz = AD2S1200_HZ;
 139        spi->mode = SPI_MODE_3;
 140        spi_setup(spi);
 141
 142        return 0;
 143
 144error_free_dev:
 145        iio_device_free(indio_dev);
 146error_ret:
 147        for (--pn; pn >= 0; pn--)
 148                gpio_free(pins[pn]);
 149        return ret;
 150}
 151
 152static int ad2s1200_remove(struct spi_device *spi)
 153{
 154        iio_device_unregister(spi_get_drvdata(spi));
 155        iio_device_free(spi_get_drvdata(spi));
 156
 157        return 0;
 158}
 159
 160static const struct spi_device_id ad2s1200_id[] = {
 161        { "ad2s1200" },
 162        { "ad2s1205" },
 163        {}
 164};
 165MODULE_DEVICE_TABLE(spi, ad2s1200_id);
 166
 167static struct spi_driver ad2s1200_driver = {
 168        .driver = {
 169                .name = DRV_NAME,
 170                .owner = THIS_MODULE,
 171        },
 172        .probe = ad2s1200_probe,
 173        .remove = ad2s1200_remove,
 174        .id_table = ad2s1200_id,
 175};
 176module_spi_driver(ad2s1200_driver);
 177
 178MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>");
 179MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver");
 180MODULE_LICENSE("GPL v2");
 181