linux/drivers/iio/resolver/ad2s1200.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ad2s1200.c simple support for the ADI Resolver to Digital Converters:
   4 * AD2S1200/1205
   5 *
   6 * Copyright (c) 2018-2018 David Veenstra <davidjulianveenstra@gmail.com>
   7 * Copyright (c) 2010-2010 Analog Devices Inc.
   8 */
   9
  10#include <linux/bitops.h>
  11#include <linux/delay.h>
  12#include <linux/device.h>
  13#include <linux/gpio/consumer.h>
  14#include <linux/module.h>
  15#include <linux/mod_devicetable.h>
  16#include <linux/mutex.h>
  17#include <linux/spi/spi.h>
  18#include <linux/sysfs.h>
  19#include <linux/types.h>
  20
  21#include <linux/iio/iio.h>
  22#include <linux/iio/sysfs.h>
  23
  24#define DRV_NAME "ad2s1200"
  25
  26/* input clock on serial interface */
  27#define AD2S1200_HZ     8192000
  28/* clock period in nano second */
  29#define AD2S1200_TSCLK  (1000000000 / AD2S1200_HZ)
  30
  31/**
  32 * struct ad2s1200_state - driver instance specific data.
  33 * @lock:       protects both the GPIO pins and the rx buffer.
  34 * @sdev:       spi device.
  35 * @sample:     GPIO pin SAMPLE.
  36 * @rdvel:      GPIO pin RDVEL.
  37 * @rx:         buffer for spi transfers.
  38 */
  39struct ad2s1200_state {
  40        struct mutex lock;
  41        struct spi_device *sdev;
  42        struct gpio_desc *sample;
  43        struct gpio_desc *rdvel;
  44        __be16 rx ____cacheline_aligned;
  45};
  46
  47static int ad2s1200_read_raw(struct iio_dev *indio_dev,
  48                             struct iio_chan_spec const *chan,
  49                             int *val,
  50                             int *val2,
  51                             long m)
  52{
  53        struct ad2s1200_state *st = iio_priv(indio_dev);
  54        int ret;
  55
  56        switch (m) {
  57        case IIO_CHAN_INFO_SCALE:
  58                switch (chan->type) {
  59                case IIO_ANGL:
  60                        /* 2 * Pi / (2^12 - 1) ~= 0.001534355 */
  61                        *val = 0;
  62                        *val2 = 1534355;
  63                        return IIO_VAL_INT_PLUS_NANO;
  64                case IIO_ANGL_VEL:
  65                        /* 2 * Pi ~= 6.283185 */
  66                        *val = 6;
  67                        *val2 = 283185;
  68                        return IIO_VAL_INT_PLUS_MICRO;
  69                default:
  70                        return -EINVAL;
  71                }
  72                break;
  73        case IIO_CHAN_INFO_RAW:
  74                mutex_lock(&st->lock);
  75                gpiod_set_value(st->sample, 0);
  76
  77                /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */
  78                udelay(1);
  79                gpiod_set_value(st->sample, 1);
  80                gpiod_set_value(st->rdvel, !!(chan->type == IIO_ANGL));
  81
  82                ret = spi_read(st->sdev, &st->rx, 2);
  83                if (ret < 0) {
  84                        mutex_unlock(&st->lock);
  85                        return ret;
  86                }
  87
  88                switch (chan->type) {
  89                case IIO_ANGL:
  90                        *val = be16_to_cpup(&st->rx) >> 4;
  91                        break;
  92                case IIO_ANGL_VEL:
  93                        *val = sign_extend32(be16_to_cpup(&st->rx) >> 4, 11);
  94                        break;
  95                default:
  96                        mutex_unlock(&st->lock);
  97                        return -EINVAL;
  98                }
  99
 100                /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */
 101                udelay(1);
 102                mutex_unlock(&st->lock);
 103
 104                return IIO_VAL_INT;
 105        default:
 106                break;
 107        }
 108
 109        return -EINVAL;
 110}
 111
 112static const struct iio_chan_spec ad2s1200_channels[] = {
 113        {
 114                .type = IIO_ANGL,
 115                .indexed = 1,
 116                .channel = 0,
 117                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 118                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 119        }, {
 120                .type = IIO_ANGL_VEL,
 121                .indexed = 1,
 122                .channel = 0,
 123                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 124                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 125        }
 126};
 127
 128static const struct iio_info ad2s1200_info = {
 129        .read_raw = ad2s1200_read_raw,
 130};
 131
 132static int ad2s1200_probe(struct spi_device *spi)
 133{
 134        struct ad2s1200_state *st;
 135        struct iio_dev *indio_dev;
 136        int ret;
 137
 138        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 139        if (!indio_dev)
 140                return -ENOMEM;
 141
 142        spi_set_drvdata(spi, indio_dev);
 143        st = iio_priv(indio_dev);
 144        mutex_init(&st->lock);
 145        st->sdev = spi;
 146
 147        st->sample = devm_gpiod_get(&spi->dev, "adi,sample", GPIOD_OUT_LOW);
 148        if (IS_ERR(st->sample)) {
 149                dev_err(&spi->dev, "Failed to claim SAMPLE gpio: err=%ld\n",
 150                        PTR_ERR(st->sample));
 151                return PTR_ERR(st->sample);
 152        }
 153
 154        st->rdvel = devm_gpiod_get(&spi->dev, "adi,rdvel", GPIOD_OUT_LOW);
 155        if (IS_ERR(st->rdvel)) {
 156                dev_err(&spi->dev, "Failed to claim RDVEL gpio: err=%ld\n",
 157                        PTR_ERR(st->rdvel));
 158                return PTR_ERR(st->rdvel);
 159        }
 160
 161        indio_dev->info = &ad2s1200_info;
 162        indio_dev->modes = INDIO_DIRECT_MODE;
 163        indio_dev->channels = ad2s1200_channels;
 164        indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels);
 165        indio_dev->name = spi_get_device_id(spi)->name;
 166
 167        spi->max_speed_hz = AD2S1200_HZ;
 168        spi->mode = SPI_MODE_3;
 169        ret = spi_setup(spi);
 170
 171        if (ret < 0) {
 172                dev_err(&spi->dev, "spi_setup failed!\n");
 173                return ret;
 174        }
 175
 176        return devm_iio_device_register(&spi->dev, indio_dev);
 177}
 178
 179static const struct of_device_id ad2s1200_of_match[] = {
 180        { .compatible = "adi,ad2s1200", },
 181        { .compatible = "adi,ad2s1205", },
 182        { }
 183};
 184MODULE_DEVICE_TABLE(of, ad2s1200_of_match);
 185
 186static const struct spi_device_id ad2s1200_id[] = {
 187        { "ad2s1200" },
 188        { "ad2s1205" },
 189        {}
 190};
 191MODULE_DEVICE_TABLE(spi, ad2s1200_id);
 192
 193static struct spi_driver ad2s1200_driver = {
 194        .driver = {
 195                .name = DRV_NAME,
 196                .of_match_table = ad2s1200_of_match,
 197        },
 198        .probe = ad2s1200_probe,
 199        .id_table = ad2s1200_id,
 200};
 201module_spi_driver(ad2s1200_driver);
 202
 203MODULE_AUTHOR("David Veenstra <davidjulianveenstra@gmail.com>");
 204MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>");
 205MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver");
 206MODULE_LICENSE("GPL v2");
 207