On Tue, Nov 06, 2007 at 02:33:53AM -0800, akpm@linux-foundation.org wrote:
[mmotm.git] / drivers / staging / iio / accel / kxsd9.c
blob33d16b6f7b50089eca6c915d0caa3f6d8deae37a
1 /*
2 * kxsd9.c simple support for the Kionix KXSD9 3D
3 * accelerometer.
5 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@cam.ac.uk>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * The i2c interface is very similar, so shouldn't be a problem once
12 * I have a suitable wire made up.
14 * TODO: Support the motion detector
15 * Uses register address incrementing so could have a
16 * heavily optimized ring buffer access function.
19 #include <linux/interrupt.h>
20 #include <linux/gpio.h>
21 #include <linux/fs.h>
22 #include <linux/device.h>
23 #include <linux/kernel.h>
24 #include <linux/spi/spi.h>
25 #include <linux/sysfs.h>
26 #include <linux/rtc.h>
27 #include <linux/delay.h>
29 #include "../iio.h"
30 #include "../sysfs.h"
31 #include "../adc/adc.h"
32 #include "accel.h"
34 #define KXSD9_REG_X 0x00
35 #define KXSD9_REG_Y 0x02
36 #define KXSD9_REG_Z 0x04
37 #define KXSD9_REG_AUX 0x06
38 #define KXSD9_REG_RESET 0x0a
39 #define KXSD9_REG_CTRL_C 0x0c
41 #define KXSD9_FS_8 0x00
42 #define KXSD9_FS_6 0x01
43 #define KXSD9_FS_4 0x02
44 #define KXSD9_FS_2 0x03
45 #define KXSD9_FS_MASK 0x03
47 #define KXSD9_REG_CTRL_B 0x0d
48 #define KXSD9_REG_CTRL_A 0x0e
50 #define KXSD9_READ(a) (0x80 | (a))
51 #define KXSD9_WRITE(a) (a)
53 #define IIO_DEV_ATTR_ACCEL_SET_RANGE(_mode, _show, _store) \
54 IIO_DEVICE_ATTR(accel_range, _mode, _show, _store, 0)
56 #define KXSD9_STATE_RX_SIZE 2
57 #define KXSD9_STATE_TX_SIZE 4
58 /**
59 * struct kxsd9_state - device related storage
60 * @buf_lock: protect the rx and tx buffers.
61 * @indio_dev: associated industrial IO device
62 * @us: spi device
63 * @rx: single rx buffer storage
64 * @tx: single tx buffer storage
65 **/
66 struct kxsd9_state {
67 struct mutex buf_lock;
68 struct iio_dev *indio_dev;
69 struct spi_device *us;
70 u8 *rx;
71 u8 *tx;
74 /* This may want to move to mili g to allow for non integer ranges */
75 static ssize_t kxsd9_read_accel_range(struct device *dev,
76 struct device_attribute *attr,
77 char *buf)
79 int ret;
80 ssize_t len = 0;
81 struct iio_dev *indio_dev = dev_get_drvdata(dev);
82 struct kxsd9_state *st = indio_dev->dev_data;
83 struct spi_transfer xfer = {
84 .bits_per_word = 8,
85 .len = 2,
86 .cs_change = 1,
87 .tx_buf = st->tx,
88 .rx_buf = st->rx,
90 struct spi_message msg;
92 mutex_lock(&st->buf_lock);
93 st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
94 st->tx[1] = 0;
95 spi_message_init(&msg);
96 spi_message_add_tail(&xfer, &msg);
97 ret = spi_sync(st->us, &msg);
98 if (ret)
99 goto error_ret;
101 switch (st->rx[1] & KXSD9_FS_MASK) {
102 case KXSD9_FS_8:
103 len += sprintf(buf, "8\n");
104 break;
105 case KXSD9_FS_6:
106 len += sprintf(buf, "6\n");
107 break;
108 case KXSD9_FS_4:
109 len += sprintf(buf, "4\n");
110 break;
111 case KXSD9_FS_2:
112 len += sprintf(buf, "2\n");
113 break;
116 error_ret:
117 mutex_unlock(&st->buf_lock);
119 return ret ? ret : len;
121 static ssize_t kxsd9_write_accel_range(struct device *dev,
122 struct device_attribute *attr,
123 const char *buf,
124 size_t len)
126 long readin;
127 struct spi_message msg;
128 int ret;
129 struct iio_dev *indio_dev = dev_get_drvdata(dev);
130 struct kxsd9_state *st = indio_dev->dev_data;
131 u8 val;
132 struct spi_transfer xfers[] = {
134 .bits_per_word = 8,
135 .len = 2,
136 .cs_change = 1,
137 .tx_buf = st->tx,
138 .rx_buf = st->rx,
139 }, {
140 .bits_per_word = 8,
141 .len = 2,
142 .cs_change = 1,
143 .tx_buf = st->tx,
147 ret = strict_strtol(buf, 10, &readin);
148 if (ret)
149 return ret;
150 switch (readin) {
151 case 8:
152 val = KXSD9_FS_8;
153 break;
154 case 6:
155 val = KXSD9_FS_6;
156 break;
157 case 4:
158 val = KXSD9_FS_4;
159 break;
160 case 2:
161 val = KXSD9_FS_2;
162 break;
163 default:
164 return -EINVAL;
166 mutex_lock(&st->buf_lock);
167 st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
168 st->tx[1] = 0;
169 spi_message_init(&msg);
170 spi_message_add_tail(&xfers[0], &msg);
171 ret = spi_sync(st->us, &msg);
172 if (ret)
173 goto error_ret;
174 st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C);
175 st->tx[1] = (st->rx[1] & ~KXSD9_FS_MASK) | val;
177 spi_message_init(&msg);
178 spi_message_add_tail(&xfers[1], &msg);
179 ret = spi_sync(st->us, &msg);
180 error_ret:
181 mutex_unlock(&st->buf_lock);
182 return ret ? ret : len;
184 static ssize_t kxsd9_read_accel(struct device *dev,
185 struct device_attribute *attr,
186 char *buf)
188 struct spi_message msg;
189 int ret;
190 ssize_t len = 0;
191 u16 val;
192 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
193 struct iio_dev *indio_dev = dev_get_drvdata(dev);
194 struct kxsd9_state *st = indio_dev->dev_data;
195 struct spi_transfer xfers[] = {
197 .bits_per_word = 8,
198 .len = 1,
199 .cs_change = 0,
200 .delay_usecs = 200,
201 .tx_buf = st->tx,
202 }, {
203 .bits_per_word = 8,
204 .len = 2,
205 .cs_change = 1,
206 .rx_buf = st->rx,
210 mutex_lock(&st->buf_lock);
211 st->tx[0] = KXSD9_READ(this_attr->address);
212 spi_message_init(&msg);
213 spi_message_add_tail(&xfers[0], &msg);
214 spi_message_add_tail(&xfers[1], &msg);
215 ret = spi_sync(st->us, &msg);
216 if (ret)
217 goto error_ret;
218 val = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
219 len = sprintf(buf, "%d\n", val);
220 error_ret:
221 mutex_unlock(&st->buf_lock);
223 return ret ? ret : len;
226 static IIO_DEV_ATTR_ACCEL_X(kxsd9_read_accel, KXSD9_REG_X);
227 static IIO_DEV_ATTR_ACCEL_Y(kxsd9_read_accel, KXSD9_REG_Y);
228 static IIO_DEV_ATTR_ACCEL_Z(kxsd9_read_accel, KXSD9_REG_Z);
229 static IIO_DEV_ATTR_ADC(0, kxsd9_read_accel, KXSD9_REG_AUX);
230 static IIO_DEV_ATTR_ACCEL_SET_RANGE(S_IRUGO | S_IWUSR,
231 kxsd9_read_accel_range,
232 kxsd9_write_accel_range);
234 static struct attribute *kxsd9_attributes[] = {
235 &iio_dev_attr_accel_x.dev_attr.attr,
236 &iio_dev_attr_accel_y.dev_attr.attr,
237 &iio_dev_attr_accel_z.dev_attr.attr,
238 &iio_dev_attr_adc_0.dev_attr.attr,
239 &iio_dev_attr_accel_range.dev_attr.attr,
240 NULL,
243 static const struct attribute_group kxsd9_attribute_group = {
244 .attrs = kxsd9_attributes,
247 static int __devinit kxsd9_power_up(struct spi_device *spi)
249 int ret;
250 struct spi_transfer xfers[2] = {
252 .bits_per_word = 8,
253 .len = 2,
254 .cs_change = 1,
255 }, {
256 .bits_per_word = 8,
257 .len = 2,
258 .cs_change = 1,
261 struct spi_message msg;
262 u8 *tx2;
263 u8 *tx = kmalloc(2, GFP_KERNEL);
265 if (tx == NULL) {
266 ret = -ENOMEM;
267 goto error_ret;
269 tx2 = kmalloc(2, GFP_KERNEL);
270 if (tx2 == NULL) {
271 ret = -ENOMEM;
272 goto error_free_tx;
274 tx[0] = 0x0d;
275 tx[1] = 0x40;
277 tx2[0] = 0x0c;
278 tx2[1] = 0x9b;
280 xfers[0].tx_buf = tx;
281 xfers[1].tx_buf = tx2;
282 spi_message_init(&msg);
283 spi_message_add_tail(&xfers[0], &msg);
284 spi_message_add_tail(&xfers[1], &msg);
285 ret = spi_sync(spi, &msg);
287 kfree(tx2);
288 error_free_tx:
289 kfree(tx);
290 error_ret:
291 return ret;
295 static int __devinit kxsd9_probe(struct spi_device *spi)
298 struct kxsd9_state *st;
299 int ret = 0;
301 st = kzalloc(sizeof(*st), GFP_KERNEL);
302 if (st == NULL) {
303 ret = -ENOMEM;
304 goto error_ret;
306 spi_set_drvdata(spi, st);
308 st->rx = kmalloc(sizeof(*st->rx)*KXSD9_STATE_RX_SIZE,
309 GFP_KERNEL);
310 if (st->rx == NULL) {
311 ret = -ENOMEM;
312 goto error_free_st;
314 st->tx = kmalloc(sizeof(*st->tx)*KXSD9_STATE_TX_SIZE,
315 GFP_KERNEL);
316 if (st->tx == NULL) {
317 ret = -ENOMEM;
318 goto error_free_rx;
321 st->us = spi;
322 mutex_init(&st->buf_lock);
323 st->indio_dev = iio_allocate_device();
324 if (st->indio_dev == NULL) {
325 ret = -ENOMEM;
326 goto error_free_tx;
328 st->indio_dev->dev.parent = &spi->dev;
329 /* for now */
330 st->indio_dev->num_interrupt_lines = 0;
331 st->indio_dev->event_attrs = NULL;
333 st->indio_dev->attrs = &kxsd9_attribute_group;
334 st->indio_dev->dev_data = (void *)(st);
335 st->indio_dev->driver_module = THIS_MODULE;
336 st->indio_dev->modes = INDIO_DIRECT_MODE;
338 ret = iio_device_register(st->indio_dev);
339 if (ret)
340 goto error_free_dev;
342 spi->mode = SPI_MODE_0;
343 spi_setup(spi);
344 kxsd9_power_up(spi);
346 return 0;
348 error_free_dev:
349 iio_free_device(st->indio_dev);
350 error_free_tx:
351 kfree(st->tx);
352 error_free_rx:
353 kfree(st->rx);
354 error_free_st:
355 kfree(st);
356 error_ret:
357 return ret;
360 static int __devexit kxsd9_remove(struct spi_device *spi)
362 struct kxsd9_state *st = spi_get_drvdata(spi);
364 iio_device_unregister(st->indio_dev);
365 kfree(st->tx);
366 kfree(st->rx);
367 kfree(st);
369 return 0;
372 static struct spi_driver kxsd9_driver = {
373 .driver = {
374 .name = "kxsd9",
375 .owner = THIS_MODULE,
377 .probe = kxsd9_probe,
378 .remove = __devexit_p(kxsd9_remove),
381 static __init int kxsd9_spi_init(void)
383 return spi_register_driver(&kxsd9_driver);
385 module_init(kxsd9_spi_init);
387 static __exit void kxsd9_spi_exit(void)
389 spi_unregister_driver(&kxsd9_driver);
391 module_exit(kxsd9_spi_exit);
393 MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
394 MODULE_DESCRIPTION("Kionix KXSD9 SPI driver");
395 MODULE_LICENSE("GPL v2");