kxsd9.c (84e2f6f9583f195b9851a8f6340bb526749ea609) kxsd9.c (0427a106a98adf94b53cc88607ceabc2ecebd2cc)
1/*
2 * kxsd9.c simple support for the Kionix KXSD9 3D
3 * accelerometer.
4 *
5 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>
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
1/*
2 * kxsd9.c simple support for the Kionix KXSD9 3D
3 * accelerometer.
4 *
5 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>
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/sysfs.h>
22#include <linux/slab.h>
23#include <linux/module.h>
24#include <linux/regmap.h>
25#include <linux/iio/iio.h>
26#include <linux/iio/sysfs.h>
15 */
16
17#include <linux/device.h>
18#include <linux/kernel.h>
19#include <linux/sysfs.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/regmap.h>
23#include <linux/iio/iio.h>
24#include <linux/iio/sysfs.h>
25#include <linux/iio/buffer.h>
26#include <linux/iio/triggered_buffer.h>
27#include <linux/iio/trigger_consumer.h>
27
28#include "kxsd9.h"
29
30#define KXSD9_REG_X 0x00
31#define KXSD9_REG_Y 0x02
32#define KXSD9_REG_Z 0x04
33#define KXSD9_REG_AUX 0x06
34#define KXSD9_REG_RESET 0x0a
35#define KXSD9_REG_CTRL_C 0x0c
36
37#define KXSD9_FS_MASK 0x03
38
39#define KXSD9_REG_CTRL_B 0x0d
40#define KXSD9_REG_CTRL_A 0x0e
41
42/**
43 * struct kxsd9_state - device related storage
28
29#include "kxsd9.h"
30
31#define KXSD9_REG_X 0x00
32#define KXSD9_REG_Y 0x02
33#define KXSD9_REG_Z 0x04
34#define KXSD9_REG_AUX 0x06
35#define KXSD9_REG_RESET 0x0a
36#define KXSD9_REG_CTRL_C 0x0c
37
38#define KXSD9_FS_MASK 0x03
39
40#define KXSD9_REG_CTRL_B 0x0d
41#define KXSD9_REG_CTRL_A 0x0e
42
43/**
44 * struct kxsd9_state - device related storage
45 * @dev: pointer to the parent device
44 * @map: regmap to the device
45 */
46struct kxsd9_state {
46 * @map: regmap to the device
47 */
48struct kxsd9_state {
49 struct device *dev;
47 struct regmap *map;
48};
49
50#define KXSD9_SCALE_2G "0.011978"
51#define KXSD9_SCALE_4G "0.023927"
52#define KXSD9_SCALE_6G "0.035934"
53#define KXSD9_SCALE_8G "0.047853"
54

--- 95 unchanged lines hidden (view full) ---

150 *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK];
151 ret = IIO_VAL_INT_PLUS_MICRO;
152 break;
153 }
154
155error_ret:
156 return ret;
157};
50 struct regmap *map;
51};
52
53#define KXSD9_SCALE_2G "0.011978"
54#define KXSD9_SCALE_4G "0.023927"
55#define KXSD9_SCALE_6G "0.035934"
56#define KXSD9_SCALE_8G "0.047853"
57

--- 95 unchanged lines hidden (view full) ---

153 *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK];
154 ret = IIO_VAL_INT_PLUS_MICRO;
155 break;
156 }
157
158error_ret:
159 return ret;
160};
158#define KXSD9_ACCEL_CHAN(axis) \
161
162static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
163{
164 const struct iio_poll_func *pf = p;
165 struct iio_dev *indio_dev = pf->indio_dev;
166 struct kxsd9_state *st = iio_priv(indio_dev);
167 int ret;
168 /* 4 * 16bit values AND timestamp */
169 __be16 hw_values[8];
170
171 ret = regmap_bulk_read(st->map,
172 KXSD9_REG_X,
173 &hw_values,
174 8);
175 if (ret) {
176 dev_err(st->dev,
177 "error reading data\n");
178 return ret;
179 }
180
181 iio_push_to_buffers_with_timestamp(indio_dev,
182 hw_values,
183 iio_get_time_ns(indio_dev));
184 iio_trigger_notify_done(indio_dev->trig);
185
186 return IRQ_HANDLED;
187}
188
189#define KXSD9_ACCEL_CHAN(axis, index) \
159 { \
160 .type = IIO_ACCEL, \
161 .modified = 1, \
162 .channel2 = IIO_MOD_##axis, \
163 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
164 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
165 BIT(IIO_CHAN_INFO_OFFSET), \
166 .address = KXSD9_REG_##axis, \
190 { \
191 .type = IIO_ACCEL, \
192 .modified = 1, \
193 .channel2 = IIO_MOD_##axis, \
194 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
195 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
196 BIT(IIO_CHAN_INFO_OFFSET), \
197 .address = KXSD9_REG_##axis, \
198 .scan_index = index, \
199 .scan_type = { \
200 .sign = 'u', \
201 .realbits = 12, \
202 .storagebits = 16, \
203 .shift = 4, \
204 .endianness = IIO_BE, \
205 }, \
167 }
168
169static const struct iio_chan_spec kxsd9_channels[] = {
206 }
207
208static const struct iio_chan_spec kxsd9_channels[] = {
170 KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
209 KXSD9_ACCEL_CHAN(X, 0),
210 KXSD9_ACCEL_CHAN(Y, 1),
211 KXSD9_ACCEL_CHAN(Z, 2),
171 {
172 .type = IIO_VOLTAGE,
173 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
174 .indexed = 1,
175 .address = KXSD9_REG_AUX,
212 {
213 .type = IIO_VOLTAGE,
214 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
215 .indexed = 1,
216 .address = KXSD9_REG_AUX,
176 }
217 .scan_index = 3,
218 .scan_type = {
219 .sign = 'u',
220 .realbits = 12,
221 .storagebits = 16,
222 .shift = 4,
223 .endianness = IIO_BE,
224 },
225 },
226 IIO_CHAN_SOFT_TIMESTAMP(4),
177};
178
179static const struct attribute_group kxsd9_attribute_group = {
180 .attrs = kxsd9_attributes,
181};
182
183static int kxsd9_power_up(struct kxsd9_state *st)
184{

--- 7 unchanged lines hidden (view full) ---

192
193static const struct iio_info kxsd9_info = {
194 .read_raw = &kxsd9_read_raw,
195 .write_raw = &kxsd9_write_raw,
196 .attrs = &kxsd9_attribute_group,
197 .driver_module = THIS_MODULE,
198};
199
227};
228
229static const struct attribute_group kxsd9_attribute_group = {
230 .attrs = kxsd9_attributes,
231};
232
233static int kxsd9_power_up(struct kxsd9_state *st)
234{

--- 7 unchanged lines hidden (view full) ---

242
243static const struct iio_info kxsd9_info = {
244 .read_raw = &kxsd9_read_raw,
245 .write_raw = &kxsd9_write_raw,
246 .attrs = &kxsd9_attribute_group,
247 .driver_module = THIS_MODULE,
248};
249
250/* Four channels apart from timestamp, scan mask = 0x0f */
251static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 };
252
200int kxsd9_common_probe(struct device *parent,
201 struct regmap *map,
202 const char *name)
203{
204 struct iio_dev *indio_dev;
205 struct kxsd9_state *st;
206 int ret;
207
208 indio_dev = devm_iio_device_alloc(parent, sizeof(*st));
209 if (!indio_dev)
210 return -ENOMEM;
211
212 st = iio_priv(indio_dev);
253int kxsd9_common_probe(struct device *parent,
254 struct regmap *map,
255 const char *name)
256{
257 struct iio_dev *indio_dev;
258 struct kxsd9_state *st;
259 int ret;
260
261 indio_dev = devm_iio_device_alloc(parent, sizeof(*st));
262 if (!indio_dev)
263 return -ENOMEM;
264
265 st = iio_priv(indio_dev);
266 st->dev = parent;
213 st->map = map;
214
215 indio_dev->channels = kxsd9_channels;
216 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
217 indio_dev->name = name;
218 indio_dev->dev.parent = parent;
219 indio_dev->info = &kxsd9_info;
220 indio_dev->modes = INDIO_DIRECT_MODE;
267 st->map = map;
268
269 indio_dev->channels = kxsd9_channels;
270 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
271 indio_dev->name = name;
272 indio_dev->dev.parent = parent;
273 indio_dev->info = &kxsd9_info;
274 indio_dev->modes = INDIO_DIRECT_MODE;
275 indio_dev->available_scan_masks = kxsd9_scan_masks;
221
222 kxsd9_power_up(st);
223
276
277 kxsd9_power_up(st);
278
279 ret = iio_triggered_buffer_setup(indio_dev,
280 iio_pollfunc_store_time,
281 kxsd9_trigger_handler,
282 NULL);
283 if (ret) {
284 dev_err(parent, "triggered buffer setup failed\n");
285 return ret;
286 }
287
224 ret = iio_device_register(indio_dev);
225 if (ret)
288 ret = iio_device_register(indio_dev);
289 if (ret)
226 return ret;
290 goto err_cleanup_buffer;
227
228 dev_set_drvdata(parent, indio_dev);
229
230 return 0;
291
292 dev_set_drvdata(parent, indio_dev);
293
294 return 0;
295
296err_cleanup_buffer:
297 iio_triggered_buffer_cleanup(indio_dev);
298
299 return ret;
231}
232EXPORT_SYMBOL(kxsd9_common_probe);
233
234int kxsd9_common_remove(struct device *parent)
235{
236 struct iio_dev *indio_dev = dev_get_drvdata(parent);
237
300}
301EXPORT_SYMBOL(kxsd9_common_probe);
302
303int kxsd9_common_remove(struct device *parent)
304{
305 struct iio_dev *indio_dev = dev_get_drvdata(parent);
306
307 iio_triggered_buffer_cleanup(indio_dev);
238 iio_device_unregister(indio_dev);
239
240 return 0;
241}
242EXPORT_SYMBOL(kxsd9_common_remove);
243
244MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
245MODULE_DESCRIPTION("Kionix KXSD9 driver");
246MODULE_LICENSE("GPL v2");
308 iio_device_unregister(indio_dev);
309
310 return 0;
311}
312EXPORT_SYMBOL(kxsd9_common_remove);
313
314MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
315MODULE_DESCRIPTION("Kionix KXSD9 driver");
316MODULE_LICENSE("GPL v2");