2 * kxsd9.c simple support for the Kionix KXSD9 3D
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>
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>
31 #include "../adc/adc.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
59 * struct kxsd9_state - device related storage
60 * @buf_lock: protect the rx and tx buffers.
61 * @indio_dev: associated industrial IO device
63 * @rx: single rx buffer storage
64 * @tx: single tx buffer storage
67 struct mutex buf_lock;
68 struct iio_dev *indio_dev;
69 struct spi_device *us;
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,
81 struct iio_dev *indio_dev = dev_get_drvdata(dev);
82 struct kxsd9_state *st = indio_dev->dev_data;
83 struct spi_transfer xfer = {
90 struct spi_message msg;
92 mutex_lock(&st->buf_lock);
93 st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
95 spi_message_init(&msg);
96 spi_message_add_tail(&xfer, &msg);
97 ret = spi_sync(st->us, &msg);
101 switch (st->rx[1] & KXSD9_FS_MASK) {
103 len += sprintf(buf, "8\n");
106 len += sprintf(buf, "6\n");
109 len += sprintf(buf, "4\n");
112 len += sprintf(buf, "2\n");
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,
127 struct spi_message msg;
129 struct iio_dev *indio_dev = dev_get_drvdata(dev);
130 struct kxsd9_state *st = indio_dev->dev_data;
132 struct spi_transfer xfers[] = {
147 ret = strict_strtol(buf, 10, &readin);
166 mutex_lock(&st->buf_lock);
167 st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C);
169 spi_message_init(&msg);
170 spi_message_add_tail(&xfers[0], &msg);
171 ret = spi_sync(st->us, &msg);
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);
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,
188 struct spi_message msg;
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[] = {
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);
218 val = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
219 len = sprintf(buf, "%d\n", val);
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,
243 static const struct attribute_group kxsd9_attribute_group = {
244 .attrs = kxsd9_attributes,
247 static int __devinit kxsd9_power_up(struct spi_device *spi)
250 struct spi_transfer xfers[2] = {
261 struct spi_message msg;
263 u8 *tx = kmalloc(2, GFP_KERNEL);
269 tx2 = kmalloc(2, GFP_KERNEL);
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);
295 static int __devinit kxsd9_probe(struct spi_device *spi)
298 struct kxsd9_state *st;
301 st = kzalloc(sizeof(*st), GFP_KERNEL);
306 spi_set_drvdata(spi, st);
308 st->rx = kmalloc(sizeof(*st->rx)*KXSD9_STATE_RX_SIZE,
310 if (st->rx == NULL) {
314 st->tx = kmalloc(sizeof(*st->tx)*KXSD9_STATE_TX_SIZE,
316 if (st->tx == NULL) {
322 mutex_init(&st->buf_lock);
323 st->indio_dev = iio_allocate_device();
324 if (st->indio_dev == NULL) {
328 st->indio_dev->dev.parent = &spi->dev;
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);
342 spi->mode = SPI_MODE_0;
349 iio_free_device(st->indio_dev);
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);
372 static struct spi_driver kxsd9_driver = {
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");