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