blob: e24c5890652f8d1c1b0280875f25cde6fb0050a5 [file] [log] [blame]
Graf Yangf46d9f12010-10-27 21:44:19 -04001/*
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>
Paul Gortmaker99c97852011-07-03 15:49:50 -040017#include <linux/module.h>
Graf Yangf46d9f12010-10-27 21:44:19 -040018
Jonathan Cameron06458e22012-04-25 15:54:58 +010019#include <linux/iio/iio.h>
20#include <linux/iio/sysfs.h>
Graf Yangf46d9f12010-10-27 21:44:19 -040021
Graf Yangf46d9f12010-10-27 21:44:19 -040022struct ad2s90_state {
23 struct mutex lock;
Graf Yangf46d9f12010-10-27 21:44:19 -040024 struct spi_device *sdev;
Jonathan Cameron58f08b02011-06-27 13:07:53 +010025 u8 rx[2] ____cacheline_aligned;
Graf Yangf46d9f12010-10-27 21:44:19 -040026};
27
Jonathan Cameron199d8472011-10-05 15:27:58 +010028static 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)
Graf Yangf46d9f12010-10-27 21:44:19 -040033{
Graf Yangf46d9f12010-10-27 21:44:19 -040034 int ret;
Jonathan Cameron199d8472011-10-05 15:27:58 +010035 struct ad2s90_state *st = iio_priv(indio_dev);
Graf Yangf46d9f12010-10-27 21:44:19 -040036
Graf Yangf46d9f12010-10-27 21:44:19 -040037 mutex_lock(&st->lock);
Jonathan Cameron58f08b02011-06-27 13:07:53 +010038 ret = spi_read(st->sdev, st->rx, 2);
Graf Yangf46d9f12010-10-27 21:44:19 -040039 if (ret)
40 goto error_ret;
Jonathan Cameron199d8472011-10-05 15:27:58 +010041 *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
42
Graf Yangf46d9f12010-10-27 21:44:19 -040043error_ret:
44 mutex_unlock(&st->lock);
45
Jonathan Cameron199d8472011-10-05 15:27:58 +010046 return IIO_VAL_INT;
Graf Yangf46d9f12010-10-27 21:44:19 -040047}
48
Jonathan Cameron6fe81352011-05-18 14:42:37 +010049static const struct iio_info ad2s90_info = {
Jonathan Cameron199d8472011-10-05 15:27:58 +010050 .read_raw = &ad2s90_read_raw,
Jonathan Cameron6fe81352011-05-18 14:42:37 +010051 .driver_module = THIS_MODULE,
52};
53
Jonathan Cameron199d8472011-10-05 15:27:58 +010054static const struct iio_chan_spec ad2s90_chan = {
55 .type = IIO_ANGL,
56 .indexed = 1,
57 .channel = 0,
Jonathan Cameron3589ba92013-02-27 19:41:51 +000058 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
Jonathan Cameron199d8472011-10-05 15:27:58 +010059};
60
Bill Pemberton4ae1c612012-11-19 13:21:57 -050061static int ad2s90_probe(struct spi_device *spi)
Graf Yangf46d9f12010-10-27 21:44:19 -040062{
Jonathan Cameron58f08b02011-06-27 13:07:53 +010063 struct iio_dev *indio_dev;
Graf Yangf46d9f12010-10-27 21:44:19 -040064 struct ad2s90_state *st;
65 int ret = 0;
66
Sachin Kamat6bba7982013-09-11 10:55:00 +010067 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
68 if (!indio_dev)
69 return -ENOMEM;
Jonathan Cameron58f08b02011-06-27 13:07:53 +010070 st = iio_priv(indio_dev);
71 spi_set_drvdata(spi, indio_dev);
Graf Yangf46d9f12010-10-27 21:44:19 -040072
73 mutex_init(&st->lock);
74 st->sdev = spi;
Jonathan Cameron58f08b02011-06-27 13:07:53 +010075 indio_dev->dev.parent = &spi->dev;
76 indio_dev->info = &ad2s90_info;
77 indio_dev->modes = INDIO_DIRECT_MODE;
Jonathan Cameron199d8472011-10-05 15:27:58 +010078 indio_dev->channels = &ad2s90_chan;
79 indio_dev->num_channels = 1;
Jonathan Cameron19147f52011-10-05 15:27:57 +010080 indio_dev->name = spi_get_device_id(spi)->name;
Graf Yangf46d9f12010-10-27 21:44:19 -040081
Jonathan Cameron72a86cc2011-10-05 15:27:56 +010082 ret = iio_device_register(indio_dev);
Graf Yangf46d9f12010-10-27 21:44:19 -040083 if (ret)
Sachin Kamat6bba7982013-09-11 10:55:00 +010084 return ret;
Graf Yangf46d9f12010-10-27 21:44:19 -040085
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;
Graf Yangf46d9f12010-10-27 21:44:19 -040092}
93
Bill Pemberton447d4f22012-11-19 13:26:37 -050094static int ad2s90_remove(struct spi_device *spi)
Graf Yangf46d9f12010-10-27 21:44:19 -040095{
Jonathan Cameron58f08b02011-06-27 13:07:53 +010096 iio_device_unregister(spi_get_drvdata(spi));
Graf Yangf46d9f12010-10-27 21:44:19 -040097
98 return 0;
99}
100
Jonathan Cameron19147f52011-10-05 15:27:57 +0100101static const struct spi_device_id ad2s90_id[] = {
102 { "ad2s90" },
103 {}
104};
Lars-Peter Clausen55e43902011-11-16 08:53:31 +0100105MODULE_DEVICE_TABLE(spi, ad2s90_id);
Jonathan Cameron19147f52011-10-05 15:27:57 +0100106
Graf Yangf46d9f12010-10-27 21:44:19 -0400107static struct spi_driver ad2s90_driver = {
108 .driver = {
Jonathan Cameron19147f52011-10-05 15:27:57 +0100109 .name = "ad2s90",
Graf Yangf46d9f12010-10-27 21:44:19 -0400110 .owner = THIS_MODULE,
111 },
112 .probe = ad2s90_probe,
Bill Pembertone543acf2012-11-19 13:21:38 -0500113 .remove = ad2s90_remove,
Jonathan Cameron19147f52011-10-05 15:27:57 +0100114 .id_table = ad2s90_id,
Graf Yangf46d9f12010-10-27 21:44:19 -0400115};
Lars-Peter Clausenae6ae6f2011-11-16 10:13:39 +0100116module_spi_driver(ad2s90_driver);
Graf Yangf46d9f12010-10-27 21:44:19 -0400117
118MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>");
119MODULE_DESCRIPTION("Analog Devices AD2S90 Resolver to Digital SPI driver");
120MODULE_LICENSE("GPL v2");