1/* 2 * ad2s90.c simple support for the ADI Resolver to Digital Converters: AD2S90 3 * 4 * Copyright (c) 2010-2010 Analog Devices Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 */ 11#include <linux/types.h> 12#include <linux/mutex.h> 13#include <linux/device.h> 14#include <linux/spi/spi.h> 15#include <linux/slab.h> 16#include <linux/sysfs.h> 17#include <linux/module.h> 18 19#include <linux/iio/iio.h> 20#include <linux/iio/sysfs.h> 21 22struct ad2s90_state { 23 struct mutex lock; 24 struct spi_device *sdev; 25 u8 rx[2] ____cacheline_aligned; 26}; 27 28static int ad2s90_read_raw(struct iio_dev *indio_dev, 29 struct iio_chan_spec const *chan, 30 int *val, 31 int *val2, 32 long m) 33{ 34 int ret; 35 struct ad2s90_state *st = iio_priv(indio_dev); 36 37 mutex_lock(&st->lock); 38 ret = spi_read(st->sdev, st->rx, 2); 39 if (ret) 40 goto error_ret; 41 *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); 42 43error_ret: 44 mutex_unlock(&st->lock); 45 46 return IIO_VAL_INT; 47} 48 49static const struct iio_info ad2s90_info = { 50 .read_raw = &ad2s90_read_raw, 51 .driver_module = THIS_MODULE, 52}; 53 54static const struct iio_chan_spec ad2s90_chan = { 55 .type = IIO_ANGL, 56 .indexed = 1, 57 .channel = 0, 58 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 59}; 60 61static int ad2s90_probe(struct spi_device *spi) 62{ 63 struct iio_dev *indio_dev; 64 struct ad2s90_state *st; 65 int ret = 0; 66 67 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 68 if (!indio_dev) 69 return -ENOMEM; 70 st = iio_priv(indio_dev); 71 spi_set_drvdata(spi, indio_dev); 72 73 mutex_init(&st->lock); 74 st->sdev = spi; 75 indio_dev->dev.parent = &spi->dev; 76 indio_dev->info = &ad2s90_info; 77 indio_dev->modes = INDIO_DIRECT_MODE; 78 indio_dev->channels = &ad2s90_chan; 79 indio_dev->num_channels = 1; 80 indio_dev->name = spi_get_device_id(spi)->name; 81 82 ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); 83 if (ret) 84 return ret; 85 86 /* need 600ns between CS and the first falling edge of SCLK */ 87 spi->max_speed_hz = 830000; 88 spi->mode = SPI_MODE_3; 89 spi_setup(spi); 90 91 return 0; 92} 93 94static const struct spi_device_id ad2s90_id[] = { 95 { "ad2s90" }, 96 {} 97}; 98MODULE_DEVICE_TABLE(spi, ad2s90_id); 99 100static struct spi_driver ad2s90_driver = { 101 .driver = { 102 .name = "ad2s90", 103 }, 104 .probe = ad2s90_probe, 105 .id_table = ad2s90_id, 106}; 107module_spi_driver(ad2s90_driver); 108 109MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); 110MODULE_DESCRIPTION("Analog Devices AD2S90 Resolver to Digital SPI driver"); 111MODULE_LICENSE("GPL v2"); 112