Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci
[deliverable/linux.git] / drivers / staging / iio / gyro / adis16080_core.c
CommitLineData
1b2f99e1
BS
1/*
2 * ADIS16080/100 Yaw Rate Gyroscope with SPI driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
1b2f99e1
BS
8#include <linux/delay.h>
9#include <linux/mutex.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/spi/spi.h>
13#include <linux/slab.h>
14#include <linux/sysfs.h>
99c97852 15#include <linux/module.h>
1b2f99e1
BS
16
17#include "../iio.h"
18#include "../sysfs.h"
1b2f99e1 19
35d2b6f9
JC
20#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */
21#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */
22#define ADIS16080_DIN_AIN1 (2 << 10)
23#define ADIS16080_DIN_AIN2 (3 << 10)
24
25/*
26 * 1: Write contents on DIN to control register.
27 * 0: No changes to control register.
28 */
29
30#define ADIS16080_DIN_WRITE (1 << 15)
31
32/**
33 * struct adis16080_state - device instance specific data
34 * @us: actual spi_device to write data
25985edc 35 * @buf: transmit or receive buffer
35d2b6f9
JC
36 * @buf_lock: mutex to protect tx and rx
37 **/
38struct adis16080_state {
39 struct spi_device *us;
35d2b6f9
JC
40 struct mutex buf_lock;
41
42 u8 buf[2] ____cacheline_aligned;
43};
1b2f99e1 44
584c81fb 45static int adis16080_spi_write(struct iio_dev *indio_dev,
1b2f99e1
BS
46 u16 val)
47{
48 int ret;
1dd9290a 49 struct adis16080_state *st = iio_priv(indio_dev);
1b2f99e1
BS
50
51 mutex_lock(&st->buf_lock);
35d2b6f9
JC
52 st->buf[0] = val >> 8;
53 st->buf[1] = val;
1b2f99e1 54
35d2b6f9 55 ret = spi_write(st->us, st->buf, 2);
1b2f99e1
BS
56 mutex_unlock(&st->buf_lock);
57
58 return ret;
59}
60
584c81fb
JC
61static int adis16080_spi_read(struct iio_dev *indio_dev,
62 u16 *val)
1b2f99e1
BS
63{
64 int ret;
1dd9290a 65 struct adis16080_state *st = iio_priv(indio_dev);
1b2f99e1
BS
66
67 mutex_lock(&st->buf_lock);
68
35d2b6f9 69 ret = spi_read(st->us, st->buf, 2);
1b2f99e1
BS
70
71 if (ret == 0)
35d2b6f9 72 *val = ((st->buf[0] & 0xF) << 8) | st->buf[1];
1b2f99e1
BS
73 mutex_unlock(&st->buf_lock);
74
75 return ret;
76}
77
584c81fb
JC
78static int adis16080_read_raw(struct iio_dev *indio_dev,
79 struct iio_chan_spec const *chan,
80 int *val,
81 int *val2,
82 long mask)
1b2f99e1 83{
584c81fb
JC
84 int ret = -EINVAL;
85 u16 ut;
1b2f99e1 86 /* Take the iio_dev status lock */
584c81fb 87
1b2f99e1 88 mutex_lock(&indio_dev->mlock);
584c81fb
JC
89 switch (mask) {
90 case 0:
91 ret = adis16080_spi_write(indio_dev,
92 chan->address |
93 ADIS16080_DIN_WRITE);
94 if (ret < 0)
95 break;
96 ret = adis16080_spi_read(indio_dev, &ut);
97 if (ret < 0)
98 break;
99 *val = ut;
100 ret = IIO_VAL_INT;
101 break;
102 }
1b2f99e1
BS
103 mutex_unlock(&indio_dev->mlock);
104
584c81fb 105 return ret;
1b2f99e1 106}
1b2f99e1 107
584c81fb
JC
108static const struct iio_chan_spec adis16080_channels[] = {
109 {
41ea040c 110 .type = IIO_ANGL_VEL,
584c81fb
JC
111 .modified = 1,
112 .channel2 = IIO_MOD_Z,
113 .address = ADIS16080_DIN_GYRO,
114 }, {
6835cb6b 115 .type = IIO_VOLTAGE,
584c81fb
JC
116 .indexed = 1,
117 .channel = 0,
118 .address = ADIS16080_DIN_AIN1,
119 }, {
6835cb6b 120 .type = IIO_VOLTAGE,
584c81fb
JC
121 .indexed = 1,
122 .channel = 1,
123 .address = ADIS16080_DIN_AIN2,
124 }, {
125 .type = IIO_TEMP,
126 .indexed = 1,
127 .channel = 0,
128 .address = ADIS16080_DIN_TEMP,
129 }
1b2f99e1
BS
130};
131
6fe8135f 132static const struct iio_info adis16080_info = {
584c81fb 133 .read_raw = &adis16080_read_raw,
6fe8135f
JC
134 .driver_module = THIS_MODULE,
135};
136
1b2f99e1
BS
137static int __devinit adis16080_probe(struct spi_device *spi)
138{
26d25ae3 139 int ret;
1dd9290a
JC
140 struct adis16080_state *st;
141 struct iio_dev *indio_dev;
142
143 /* setup the industrialio driver allocated elements */
144 indio_dev = iio_allocate_device(sizeof(*st));
145 if (indio_dev == NULL) {
146 ret = -ENOMEM;
1b2f99e1
BS
147 goto error_ret;
148 }
1dd9290a 149 st = iio_priv(indio_dev);
1b2f99e1 150 /* this is only used for removal purposes */
1dd9290a 151 spi_set_drvdata(spi, indio_dev);
1b2f99e1
BS
152
153 /* Allocate the comms buffers */
1b2f99e1
BS
154 st->us = spi;
155 mutex_init(&st->buf_lock);
1b2f99e1 156
1dd9290a 157 indio_dev->name = spi->dev.driver->name;
584c81fb
JC
158 indio_dev->channels = adis16080_channels;
159 indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
1dd9290a
JC
160 indio_dev->dev.parent = &spi->dev;
161 indio_dev->info = &adis16080_info;
162 indio_dev->modes = INDIO_DIRECT_MODE;
1b2f99e1 163
1dd9290a 164 ret = iio_device_register(indio_dev);
1b2f99e1 165 if (ret)
8d016b43 166 goto error_free_dev;
1b2f99e1
BS
167 return 0;
168
1b2f99e1 169error_free_dev:
26d25ae3 170 iio_free_device(indio_dev);
1b2f99e1
BS
171error_ret:
172 return ret;
173}
174
175/* fixme, confirm ordering in this function */
176static int adis16080_remove(struct spi_device *spi)
177{
1dd9290a 178 iio_device_unregister(spi_get_drvdata(spi));
d2fffd6c 179 iio_free_device(spi_get_drvdata(spi));
1b2f99e1
BS
180
181 return 0;
182}
183
184static struct spi_driver adis16080_driver = {
185 .driver = {
186 .name = "adis16080",
187 .owner = THIS_MODULE,
188 },
189 .probe = adis16080_probe,
190 .remove = __devexit_p(adis16080_remove),
191};
ae6ae6fe 192module_spi_driver(adis16080_driver);
1b2f99e1
BS
193
194MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
8d016b43 195MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
1b2f99e1 196MODULE_LICENSE("GPL v2");
55e4390c 197MODULE_ALIAS("spi:adis16080");
This page took 0.15108 seconds and 5 git commands to generate.