Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
kxsd9.c
Go to the documentation of this file.
1 /*
2  * kxsd9.c simple support for the Kionix KXSD9 3D
3  * accelerometer.
4  *
5  * Copyright (c) 2008-2009 Jonathan Cameron <[email protected]>
6  *
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.
10  *
11  * The i2c interface is very similar, so shouldn't be a problem once
12  * I have a suitable wire made up.
13  *
14  * TODO: Support the motion detector
15  * Uses register address incrementing so could have a
16  * heavily optimized ring buffer access function.
17  */
18 
19 #include <linux/device.h>
20 #include <linux/kernel.h>
21 #include <linux/spi/spi.h>
22 #include <linux/sysfs.h>
23 #include <linux/slab.h>
24 #include <linux/module.h>
25 
26 #include <linux/iio/iio.h>
27 #include <linux/iio/sysfs.h>
28 
29 #define KXSD9_REG_X 0x00
30 #define KXSD9_REG_Y 0x02
31 #define KXSD9_REG_Z 0x04
32 #define KXSD9_REG_AUX 0x06
33 #define KXSD9_REG_RESET 0x0a
34 #define KXSD9_REG_CTRL_C 0x0c
35 
36 #define KXSD9_FS_MASK 0x03
37 
38 #define KXSD9_REG_CTRL_B 0x0d
39 #define KXSD9_REG_CTRL_A 0x0e
40 
41 #define KXSD9_READ(a) (0x80 | (a))
42 #define KXSD9_WRITE(a) (a)
43 
44 #define KXSD9_STATE_RX_SIZE 2
45 #define KXSD9_STATE_TX_SIZE 2
46 
53 struct kxsd9_state {
54  struct mutex buf_lock;
55  struct spi_device *us;
58 };
59 
60 #define KXSD9_SCALE_2G "0.011978"
61 #define KXSD9_SCALE_4G "0.023927"
62 #define KXSD9_SCALE_6G "0.035934"
63 #define KXSD9_SCALE_8G "0.047853"
64 
65 /* reverse order */
66 static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 };
67 
68 static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
69 {
70  int ret, i;
71  struct kxsd9_state *st = iio_priv(indio_dev);
72  bool foundit = false;
73 
74  for (i = 0; i < 4; i++)
75  if (micro == kxsd9_micro_scales[i]) {
76  foundit = true;
77  break;
78  }
79  if (!foundit)
80  return -EINVAL;
81 
82  mutex_lock(&st->buf_lock);
83  ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
84  if (ret)
85  goto error_ret;
87  st->tx[1] = (ret & ~KXSD9_FS_MASK) | i;
88 
89  ret = spi_write(st->us, st->tx, 2);
90 error_ret:
91  mutex_unlock(&st->buf_lock);
92  return ret;
93 }
94 
95 static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
96 {
97  struct spi_message msg;
98  int ret;
99  struct kxsd9_state *st = iio_priv(indio_dev);
100  struct spi_transfer xfers[] = {
101  {
102  .bits_per_word = 8,
103  .len = 1,
104  .delay_usecs = 200,
105  .tx_buf = st->tx,
106  }, {
107  .bits_per_word = 8,
108  .len = 2,
109  .rx_buf = st->rx,
110  },
111  };
112 
113  mutex_lock(&st->buf_lock);
114  st->tx[0] = KXSD9_READ(address);
115  spi_message_init(&msg);
116  spi_message_add_tail(&xfers[0], &msg);
117  spi_message_add_tail(&xfers[1], &msg);
118  ret = spi_sync(st->us, &msg);
119  if (ret)
120  return ret;
121  return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
122 }
123 
124 static IIO_CONST_ATTR(accel_scale_available,
125  KXSD9_SCALE_2G " "
126  KXSD9_SCALE_4G " "
127  KXSD9_SCALE_6G " "
129 
130 static struct attribute *kxsd9_attributes[] = {
131  &iio_const_attr_accel_scale_available.dev_attr.attr,
132  NULL,
133 };
134 
135 static int kxsd9_write_raw(struct iio_dev *indio_dev,
136  struct iio_chan_spec const *chan,
137  int val,
138  int val2,
139  long mask)
140 {
141  int ret = -EINVAL;
142 
143  if (mask == IIO_CHAN_INFO_SCALE) {
144  /* Check no integer component */
145  if (val)
146  return -EINVAL;
147  ret = kxsd9_write_scale(indio_dev, val2);
148  }
149 
150  return ret;
151 }
152 
153 static int kxsd9_read_raw(struct iio_dev *indio_dev,
154  struct iio_chan_spec const *chan,
155  int *val, int *val2, long mask)
156 {
157  int ret = -EINVAL;
158  struct kxsd9_state *st = iio_priv(indio_dev);
159 
160  switch (mask) {
161  case IIO_CHAN_INFO_RAW:
162  ret = kxsd9_read(indio_dev, chan->address);
163  if (ret < 0)
164  goto error_ret;
165  *val = ret;
166  break;
167  case IIO_CHAN_INFO_SCALE:
168  ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
169  if (ret)
170  goto error_ret;
171  *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
173  break;
174  };
175 
176 error_ret:
177  return ret;
178 };
179 #define KXSD9_ACCEL_CHAN(axis) \
180  { \
181  .type = IIO_ACCEL, \
182  .modified = 1, \
183  .channel2 = IIO_MOD_##axis, \
184  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
185  IIO_CHAN_INFO_SCALE_SHARED_BIT, \
186  .address = KXSD9_REG_##axis, \
187  }
188 
189 static const struct iio_chan_spec kxsd9_channels[] = {
191  {
192  .type = IIO_VOLTAGE,
193  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
194  .indexed = 1,
195  .address = KXSD9_REG_AUX,
196  }
197 };
198 
199 static const struct attribute_group kxsd9_attribute_group = {
200  .attrs = kxsd9_attributes,
201 };
202 
203 static int __devinit kxsd9_power_up(struct kxsd9_state *st)
204 {
205  int ret;
206 
207  st->tx[0] = 0x0d;
208  st->tx[1] = 0x40;
209  ret = spi_write(st->us, st->tx, 2);
210  if (ret)
211  return ret;
212 
213  st->tx[0] = 0x0c;
214  st->tx[1] = 0x9b;
215  return spi_write(st->us, st->tx, 2);
216 };
217 
218 static const struct iio_info kxsd9_info = {
219  .read_raw = &kxsd9_read_raw,
220  .write_raw = &kxsd9_write_raw,
221  .attrs = &kxsd9_attribute_group,
222  .driver_module = THIS_MODULE,
223 };
224 
225 static int __devinit kxsd9_probe(struct spi_device *spi)
226 {
227  struct iio_dev *indio_dev;
228  struct kxsd9_state *st;
229  int ret = 0;
230 
231  indio_dev = iio_device_alloc(sizeof(*st));
232  if (indio_dev == NULL) {
233  ret = -ENOMEM;
234  goto error_ret;
235  }
236  st = iio_priv(indio_dev);
237  spi_set_drvdata(spi, indio_dev);
238 
239  st->us = spi;
240  mutex_init(&st->buf_lock);
241  indio_dev->channels = kxsd9_channels;
242  indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
243  indio_dev->name = spi_get_device_id(spi)->name;
244  indio_dev->dev.parent = &spi->dev;
245  indio_dev->info = &kxsd9_info;
246  indio_dev->modes = INDIO_DIRECT_MODE;
247 
248  ret = iio_device_register(indio_dev);
249  if (ret)
250  goto error_free_dev;
251 
252  spi->mode = SPI_MODE_0;
253  spi_setup(spi);
254  kxsd9_power_up(st);
255 
256  return 0;
257 
258 error_free_dev:
259  iio_device_free(indio_dev);
260 error_ret:
261  return ret;
262 }
263 
264 static int __devexit kxsd9_remove(struct spi_device *spi)
265 {
266  iio_device_unregister(spi_get_drvdata(spi));
267  iio_device_free(spi_get_drvdata(spi));
268 
269  return 0;
270 }
271 
272 static const struct spi_device_id kxsd9_id[] = {
273  {"kxsd9", 0},
274  { },
275 };
276 MODULE_DEVICE_TABLE(spi, kxsd9_id);
277 
278 static struct spi_driver kxsd9_driver = {
279  .driver = {
280  .name = "kxsd9",
281  .owner = THIS_MODULE,
282  },
283  .probe = kxsd9_probe,
284  .remove = __devexit_p(kxsd9_remove),
285  .id_table = kxsd9_id,
286 };
287 module_spi_driver(kxsd9_driver);
288 
289 MODULE_AUTHOR("Jonathan Cameron <[email protected]>");
290 MODULE_DESCRIPTION("Kionix KXSD9 SPI driver");
291 MODULE_LICENSE("GPL v2");