2 * ADIS16080/100 Yaw Rate Gyroscope with SPI driver
4 * Copyright 2010 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
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>
20 #include "../adc/adc.h"
22 #define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */
23 #define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */
24 #define ADIS16080_DIN_AIN1 (2 << 10)
25 #define ADIS16080_DIN_AIN2 (3 << 10)
28 * 1: Write contents on DIN to control register.
29 * 0: No changes to control register.
32 #define ADIS16080_DIN_WRITE (1 << 15)
35 * struct adis16080_state - device instance specific data
36 * @us: actual spi_device to write data
37 * @indio_dev: industrial I/O device structure
38 * @buf: transmit or recieve buffer
39 * @buf_lock: mutex to protect tx and rx
41 struct adis16080_state
{
42 struct spi_device
*us
;
43 struct iio_dev
*indio_dev
;
44 struct mutex buf_lock
;
46 u8 buf
[2] ____cacheline_aligned
;
49 static int adis16080_spi_write(struct device
*dev
,
53 struct iio_dev
*indio_dev
= dev_get_drvdata(dev
);
54 struct adis16080_state
*st
= iio_dev_get_devdata(indio_dev
);
56 mutex_lock(&st
->buf_lock
);
57 st
->buf
[0] = val
>> 8;
60 ret
= spi_write(st
->us
, st
->buf
, 2);
61 mutex_unlock(&st
->buf_lock
);
66 static int adis16080_spi_read(struct device
*dev
,
70 struct iio_dev
*indio_dev
= dev_get_drvdata(dev
);
71 struct adis16080_state
*st
= iio_dev_get_devdata(indio_dev
);
73 mutex_lock(&st
->buf_lock
);
75 ret
= spi_read(st
->us
, st
->buf
, 2);
78 *val
= ((st
->buf
[0] & 0xF) << 8) | st
->buf
[1];
79 mutex_unlock(&st
->buf_lock
);
84 static ssize_t
adis16080_read(struct device
*dev
,
85 struct device_attribute
*attr
,
88 struct iio_dev_attr
*this_attr
= to_iio_dev_attr(attr
);
89 struct iio_dev
*indio_dev
= dev_get_drvdata(dev
);
93 /* Take the iio_dev status lock */
94 mutex_lock(&indio_dev
->mlock
);
95 ret
= adis16080_spi_write(dev
,
96 this_attr
->address
| ADIS16080_DIN_WRITE
);
99 ret
= adis16080_spi_read(dev
, &val
);
101 mutex_unlock(&indio_dev
->mlock
);
104 return sprintf(buf
, "%d\n", val
);
108 static IIO_DEV_ATTR_GYRO_Z(adis16080_read
, ADIS16080_DIN_GYRO
);
109 static IIO_DEVICE_ATTR(temp_raw
, S_IRUGO
, adis16080_read
, NULL
,
111 static IIO_DEV_ATTR_IN_RAW(0, adis16080_read
, ADIS16080_DIN_AIN1
);
112 static IIO_DEV_ATTR_IN_RAW(1, adis16080_read
, ADIS16080_DIN_AIN2
);
113 static IIO_CONST_ATTR(name
, "adis16080");
115 static struct attribute
*adis16080_attributes
[] = {
116 &iio_dev_attr_gyro_z_raw
.dev_attr
.attr
,
117 &iio_dev_attr_temp_raw
.dev_attr
.attr
,
118 &iio_dev_attr_in0_raw
.dev_attr
.attr
,
119 &iio_dev_attr_in1_raw
.dev_attr
.attr
,
120 &iio_const_attr_name
.dev_attr
.attr
,
124 static const struct attribute_group adis16080_attribute_group
= {
125 .attrs
= adis16080_attributes
,
128 static int __devinit
adis16080_probe(struct spi_device
*spi
)
130 int ret
, regdone
= 0;
131 struct adis16080_state
*st
= kzalloc(sizeof *st
, GFP_KERNEL
);
136 /* this is only used for removal purposes */
137 spi_set_drvdata(spi
, st
);
139 /* Allocate the comms buffers */
141 mutex_init(&st
->buf_lock
);
142 /* setup the industrialio driver allocated elements */
143 st
->indio_dev
= iio_allocate_device();
144 if (st
->indio_dev
== NULL
) {
149 st
->indio_dev
->dev
.parent
= &spi
->dev
;
150 st
->indio_dev
->attrs
= &adis16080_attribute_group
;
151 st
->indio_dev
->dev_data
= (void *)(st
);
152 st
->indio_dev
->driver_module
= THIS_MODULE
;
153 st
->indio_dev
->modes
= INDIO_DIRECT_MODE
;
155 ret
= iio_device_register(st
->indio_dev
);
164 iio_device_unregister(st
->indio_dev
);
166 iio_free_device(st
->indio_dev
);
173 /* fixme, confirm ordering in this function */
174 static int adis16080_remove(struct spi_device
*spi
)
176 struct adis16080_state
*st
= spi_get_drvdata(spi
);
177 struct iio_dev
*indio_dev
= st
->indio_dev
;
179 iio_device_unregister(indio_dev
);
185 static struct spi_driver adis16080_driver
= {
188 .owner
= THIS_MODULE
,
190 .probe
= adis16080_probe
,
191 .remove
= __devexit_p(adis16080_remove
),
194 static __init
int adis16080_init(void)
196 return spi_register_driver(&adis16080_driver
);
198 module_init(adis16080_init
);
200 static __exit
void adis16080_exit(void)
202 spi_unregister_driver(&adis16080_driver
);
204 module_exit(adis16080_exit
);
206 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
207 MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
208 MODULE_LICENSE("GPL v2");