Commit | Line | Data |
---|---|---|
fdadbce0 OK |
1 | /* |
2 | * bma180.c - IIO driver for Bosch BMA180 triaxial acceleration sensor | |
3 | * | |
4 | * Copyright 2013 Oleksandr Kravchenko <x0199363@ti.com> | |
5 | * | |
6 | * This file is subject to the terms and conditions of version 2 of | |
7 | * the GNU General Public License. See the file COPYING in the main | |
8 | * directory of this archive for more details. | |
9 | */ | |
10 | ||
11 | #include <linux/module.h> | |
12 | #include <linux/i2c.h> | |
13 | #include <linux/interrupt.h> | |
14 | #include <linux/delay.h> | |
15 | #include <linux/of.h> | |
16 | #include <linux/bitops.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/string.h> | |
19 | #include <linux/iio/iio.h> | |
20 | #include <linux/iio/sysfs.h> | |
21 | #include <linux/iio/buffer.h> | |
22 | #include <linux/iio/trigger.h> | |
23 | #include <linux/iio/trigger_consumer.h> | |
24 | #include <linux/iio/triggered_buffer.h> | |
25 | ||
26 | #define BMA180_DRV_NAME "bma180" | |
27 | #define BMA180_IRQ_NAME "bma180_event" | |
28 | ||
29 | /* Register set */ | |
30 | #define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */ | |
31 | #define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */ | |
b81fbab7 | 32 | #define BMA180_TEMP 0x08 |
fdadbce0 OK |
33 | #define BMA180_CTRL_REG0 0x0d |
34 | #define BMA180_RESET 0x10 | |
35 | #define BMA180_BW_TCS 0x20 | |
36 | #define BMA180_CTRL_REG3 0x21 | |
37 | #define BMA180_TCO_Z 0x30 | |
38 | #define BMA180_OFFSET_LSB1 0x35 | |
39 | ||
40 | /* BMA180_CTRL_REG0 bits */ | |
41 | #define BMA180_DIS_WAKE_UP BIT(0) /* Disable wake up mode */ | |
42 | #define BMA180_SLEEP BIT(1) /* 1 - chip will sleep */ | |
43 | #define BMA180_EE_W BIT(4) /* Unlock writing to addr from 0x20 */ | |
44 | #define BMA180_RESET_INT BIT(6) /* Reset pending interrupts */ | |
45 | ||
46 | /* BMA180_CTRL_REG3 bits */ | |
47 | #define BMA180_NEW_DATA_INT BIT(1) /* Intr every new accel data is ready */ | |
48 | ||
49 | /* BMA180_OFFSET_LSB1 skipping mode bit */ | |
50 | #define BMA180_SMP_SKIP BIT(0) | |
51 | ||
52 | /* Bit masks for registers bit fields */ | |
cab767d5 | 53 | #define BMA180_RANGE 0x0e /* Range of measured accel values */ |
fdadbce0 OK |
54 | #define BMA180_BW 0xf0 /* Accel bandwidth */ |
55 | #define BMA180_MODE_CONFIG 0x03 /* Config operation modes */ | |
56 | ||
57 | /* We have to write this value in reset register to do soft reset */ | |
58 | #define BMA180_RESET_VAL 0xb6 | |
59 | ||
9a70b147 | 60 | #define BMA180_ID_REG_VAL 0x03 |
fdadbce0 OK |
61 | |
62 | /* Chip power modes */ | |
63 | #define BMA180_LOW_NOISE 0x00 | |
64 | #define BMA180_LOW_POWER 0x03 | |
65 | ||
fdadbce0 | 66 | /* Defaults values */ |
c7c69e85 | 67 | #define BMA180_DEF_PMODE false |
fdadbce0 | 68 | #define BMA180_DEF_BW 20 |
381676d5 | 69 | #define BMA180_DEF_SCALE 2452 |
fdadbce0 OK |
70 | |
71 | /* Available values for sysfs */ | |
72 | #define BMA180_FLP_FREQ_AVAILABLE \ | |
73 | "10 20 40 75 150 300" | |
74 | #define BMA180_SCALE_AVAILABLE \ | |
381676d5 | 75 | "0.001275 0.001863 0.002452 0.003727 0.004903 0.009709 0.019417" |
fdadbce0 OK |
76 | |
77 | struct bma180_data { | |
78 | struct i2c_client *client; | |
79 | struct iio_trigger *trig; | |
80 | struct mutex mutex; | |
c7c69e85 | 81 | bool sleep_state; |
fdadbce0 OK |
82 | int scale; |
83 | int bw; | |
c7c69e85 | 84 | bool pmode; |
b9a6a237 | 85 | u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */ |
fdadbce0 OK |
86 | }; |
87 | ||
b81fbab7 | 88 | enum bma180_chan { |
fdadbce0 OK |
89 | AXIS_X, |
90 | AXIS_Y, | |
91 | AXIS_Z, | |
b81fbab7 | 92 | TEMP |
fdadbce0 OK |
93 | }; |
94 | ||
cab767d5 PM |
95 | static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ |
96 | static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; | |
fdadbce0 | 97 | |
b81fbab7 | 98 | static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) |
fdadbce0 | 99 | { |
fdadbce0 OK |
100 | int ret; |
101 | ||
102 | if (data->sleep_state) | |
103 | return -EBUSY; | |
104 | ||
b81fbab7 PM |
105 | switch (chan) { |
106 | case TEMP: | |
107 | ret = i2c_smbus_read_byte_data(data->client, BMA180_TEMP); | |
108 | if (ret < 0) | |
109 | dev_err(&data->client->dev, "failed to read temp register\n"); | |
110 | break; | |
111 | default: | |
112 | ret = i2c_smbus_read_word_data(data->client, | |
113 | BMA180_ACC_X_LSB + chan * 2); | |
114 | if (ret < 0) | |
115 | dev_err(&data->client->dev, | |
116 | "failed to read accel_%c register\n", | |
117 | 'x' + chan); | |
118 | } | |
fdadbce0 OK |
119 | |
120 | return ret; | |
121 | } | |
122 | ||
123 | static int bma180_set_bits(struct bma180_data *data, u8 reg, u8 mask, u8 val) | |
124 | { | |
125 | int ret = i2c_smbus_read_byte_data(data->client, reg); | |
126 | u8 reg_val = (ret & ~mask) | (val << (ffs(mask) - 1)); | |
127 | ||
128 | if (ret < 0) | |
129 | return ret; | |
130 | ||
131 | return i2c_smbus_write_byte_data(data->client, reg, reg_val); | |
132 | } | |
133 | ||
134 | static int bma180_reset_intr(struct bma180_data *data) | |
135 | { | |
136 | int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_RESET_INT, 1); | |
137 | ||
138 | if (ret) | |
139 | dev_err(&data->client->dev, "failed to reset interrupt\n"); | |
140 | ||
141 | return ret; | |
142 | } | |
143 | ||
c7c69e85 | 144 | static int bma180_set_new_data_intr_state(struct bma180_data *data, bool state) |
fdadbce0 OK |
145 | { |
146 | u8 reg_val = state ? BMA180_NEW_DATA_INT : 0x00; | |
147 | int ret = i2c_smbus_write_byte_data(data->client, BMA180_CTRL_REG3, | |
148 | reg_val); | |
149 | ||
150 | if (ret) | |
151 | goto err; | |
152 | ret = bma180_reset_intr(data); | |
153 | if (ret) | |
154 | goto err; | |
155 | ||
156 | return 0; | |
157 | ||
158 | err: | |
159 | dev_err(&data->client->dev, | |
160 | "failed to set new data interrupt state %d\n", state); | |
161 | return ret; | |
162 | } | |
163 | ||
c7c69e85 | 164 | static int bma180_set_sleep_state(struct bma180_data *data, bool state) |
fdadbce0 OK |
165 | { |
166 | int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_SLEEP, state); | |
167 | ||
168 | if (ret) { | |
169 | dev_err(&data->client->dev, | |
170 | "failed to set sleep state %d\n", state); | |
171 | return ret; | |
172 | } | |
173 | data->sleep_state = state; | |
174 | ||
175 | return 0; | |
176 | } | |
177 | ||
c7c69e85 | 178 | static int bma180_set_ee_writing_state(struct bma180_data *data, bool state) |
fdadbce0 OK |
179 | { |
180 | int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_EE_W, state); | |
181 | ||
182 | if (ret) | |
183 | dev_err(&data->client->dev, | |
184 | "failed to set ee writing state %d\n", state); | |
185 | ||
186 | return ret; | |
187 | } | |
188 | ||
189 | static int bma180_set_bw(struct bma180_data *data, int val) | |
190 | { | |
191 | int ret, i; | |
192 | ||
193 | if (data->sleep_state) | |
194 | return -EBUSY; | |
195 | ||
cab767d5 PM |
196 | for (i = 0; i < ARRAY_SIZE(bma180_bw_table); ++i) { |
197 | if (bma180_bw_table[i] == val) { | |
fdadbce0 OK |
198 | ret = bma180_set_bits(data, |
199 | BMA180_BW_TCS, BMA180_BW, i); | |
200 | if (ret) { | |
201 | dev_err(&data->client->dev, | |
202 | "failed to set bandwidth\n"); | |
203 | return ret; | |
204 | } | |
205 | data->bw = val; | |
206 | return 0; | |
207 | } | |
208 | } | |
209 | ||
210 | return -EINVAL; | |
211 | } | |
212 | ||
213 | static int bma180_set_scale(struct bma180_data *data, int val) | |
214 | { | |
215 | int ret, i; | |
216 | ||
217 | if (data->sleep_state) | |
218 | return -EBUSY; | |
219 | ||
cab767d5 PM |
220 | for (i = 0; i < ARRAY_SIZE(bma180_scale_table); ++i) |
221 | if (bma180_scale_table[i] == val) { | |
fdadbce0 OK |
222 | ret = bma180_set_bits(data, |
223 | BMA180_OFFSET_LSB1, BMA180_RANGE, i); | |
224 | if (ret) { | |
225 | dev_err(&data->client->dev, | |
226 | "failed to set scale\n"); | |
227 | return ret; | |
228 | } | |
229 | data->scale = val; | |
230 | return 0; | |
231 | } | |
232 | ||
233 | return -EINVAL; | |
234 | } | |
235 | ||
c7c69e85 | 236 | static int bma180_set_pmode(struct bma180_data *data, bool mode) |
fdadbce0 OK |
237 | { |
238 | u8 reg_val = mode ? BMA180_LOW_POWER : BMA180_LOW_NOISE; | |
239 | int ret = bma180_set_bits(data, BMA180_TCO_Z, BMA180_MODE_CONFIG, | |
240 | reg_val); | |
241 | ||
242 | if (ret) { | |
243 | dev_err(&data->client->dev, "failed to set power mode\n"); | |
244 | return ret; | |
245 | } | |
246 | data->pmode = mode; | |
247 | ||
248 | return 0; | |
249 | } | |
250 | ||
251 | static int bma180_soft_reset(struct bma180_data *data) | |
252 | { | |
253 | int ret = i2c_smbus_write_byte_data(data->client, | |
254 | BMA180_RESET, BMA180_RESET_VAL); | |
255 | ||
256 | if (ret) | |
257 | dev_err(&data->client->dev, "failed to reset the chip\n"); | |
258 | ||
259 | return ret; | |
260 | } | |
261 | ||
262 | static int bma180_chip_init(struct bma180_data *data) | |
263 | { | |
264 | /* Try to read chip_id register. It must return 0x03. */ | |
265 | int ret = i2c_smbus_read_byte_data(data->client, BMA180_CHIP_ID); | |
266 | ||
267 | if (ret < 0) | |
268 | goto err; | |
9a70b147 | 269 | if (ret != BMA180_ID_REG_VAL) { |
fdadbce0 OK |
270 | ret = -ENODEV; |
271 | goto err; | |
272 | } | |
273 | ||
274 | ret = bma180_soft_reset(data); | |
275 | if (ret) | |
276 | goto err; | |
277 | /* | |
278 | * No serial transaction should occur within minimum 10 us | |
279 | * after soft_reset command | |
280 | */ | |
281 | msleep(20); | |
282 | ||
283 | ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_DIS_WAKE_UP, 1); | |
284 | if (ret) | |
285 | goto err; | |
c7c69e85 | 286 | ret = bma180_set_ee_writing_state(data, true); |
fdadbce0 OK |
287 | if (ret) |
288 | goto err; | |
c7c69e85 | 289 | ret = bma180_set_new_data_intr_state(data, false); |
fdadbce0 OK |
290 | if (ret) |
291 | goto err; | |
292 | ret = bma180_set_bits(data, BMA180_OFFSET_LSB1, BMA180_SMP_SKIP, 1); | |
293 | if (ret) | |
294 | goto err; | |
295 | ret = bma180_set_pmode(data, BMA180_DEF_PMODE); | |
296 | if (ret) | |
297 | goto err; | |
298 | ret = bma180_set_bw(data, BMA180_DEF_BW); | |
299 | if (ret) | |
300 | goto err; | |
301 | ret = bma180_set_scale(data, BMA180_DEF_SCALE); | |
302 | if (ret) | |
303 | goto err; | |
304 | ||
305 | return 0; | |
306 | ||
307 | err: | |
308 | dev_err(&data->client->dev, "failed to init the chip\n"); | |
309 | return ret; | |
310 | } | |
311 | ||
312 | static void bma180_chip_disable(struct bma180_data *data) | |
313 | { | |
c7c69e85 | 314 | if (bma180_set_new_data_intr_state(data, false)) |
fdadbce0 | 315 | goto err; |
c7c69e85 | 316 | if (bma180_set_ee_writing_state(data, false)) |
fdadbce0 | 317 | goto err; |
c7c69e85 | 318 | if (bma180_set_sleep_state(data, true)) |
fdadbce0 OK |
319 | goto err; |
320 | ||
321 | return; | |
322 | ||
323 | err: | |
324 | dev_err(&data->client->dev, "failed to disable the chip\n"); | |
325 | } | |
326 | ||
327 | static IIO_CONST_ATTR(in_accel_filter_low_pass_3db_frequency_available, | |
328 | BMA180_FLP_FREQ_AVAILABLE); | |
329 | static IIO_CONST_ATTR(in_accel_scale_available, BMA180_SCALE_AVAILABLE); | |
330 | ||
331 | static struct attribute *bma180_attributes[] = { | |
332 | &iio_const_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, | |
333 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | |
334 | NULL, | |
335 | }; | |
336 | ||
337 | static const struct attribute_group bma180_attrs_group = { | |
338 | .attrs = bma180_attributes, | |
339 | }; | |
340 | ||
341 | static int bma180_read_raw(struct iio_dev *indio_dev, | |
342 | struct iio_chan_spec const *chan, int *val, int *val2, | |
343 | long mask) | |
344 | { | |
345 | struct bma180_data *data = iio_priv(indio_dev); | |
346 | int ret; | |
347 | ||
348 | switch (mask) { | |
349 | case IIO_CHAN_INFO_RAW: | |
350 | mutex_lock(&data->mutex); | |
b81fbab7 PM |
351 | if (iio_buffer_enabled(indio_dev)) { |
352 | mutex_unlock(&data->mutex); | |
353 | return -EBUSY; | |
354 | } | |
355 | ret = bma180_get_data_reg(data, chan->scan_index); | |
fdadbce0 OK |
356 | mutex_unlock(&data->mutex); |
357 | if (ret < 0) | |
358 | return ret; | |
b81fbab7 PM |
359 | *val = sign_extend32(ret >> chan->scan_type.shift, |
360 | chan->scan_type.realbits - 1); | |
fdadbce0 OK |
361 | return IIO_VAL_INT; |
362 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | |
363 | *val = data->bw; | |
364 | return IIO_VAL_INT; | |
365 | case IIO_CHAN_INFO_SCALE: | |
b81fbab7 PM |
366 | switch (chan->type) { |
367 | case IIO_ACCEL: | |
368 | *val = 0; | |
369 | *val2 = data->scale; | |
370 | return IIO_VAL_INT_PLUS_MICRO; | |
371 | case IIO_TEMP: | |
372 | *val = 500; | |
373 | return IIO_VAL_INT; | |
374 | default: | |
375 | return -EINVAL; | |
376 | } | |
377 | case IIO_CHAN_INFO_OFFSET: | |
378 | *val = 48; /* 0 LSB @ 24 degree C */ | |
379 | return IIO_VAL_INT; | |
fdadbce0 OK |
380 | default: |
381 | return -EINVAL; | |
382 | } | |
383 | } | |
384 | ||
385 | static int bma180_write_raw(struct iio_dev *indio_dev, | |
386 | struct iio_chan_spec const *chan, int val, int val2, long mask) | |
387 | { | |
388 | struct bma180_data *data = iio_priv(indio_dev); | |
389 | int ret; | |
390 | ||
391 | switch (mask) { | |
392 | case IIO_CHAN_INFO_SCALE: | |
393 | if (val) | |
394 | return -EINVAL; | |
395 | mutex_lock(&data->mutex); | |
396 | ret = bma180_set_scale(data, val2); | |
397 | mutex_unlock(&data->mutex); | |
398 | return ret; | |
399 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | |
9b2a4d35 PM |
400 | if (val2) |
401 | return -EINVAL; | |
fdadbce0 OK |
402 | mutex_lock(&data->mutex); |
403 | ret = bma180_set_bw(data, val); | |
404 | mutex_unlock(&data->mutex); | |
405 | return ret; | |
406 | default: | |
407 | return -EINVAL; | |
408 | } | |
409 | } | |
410 | ||
fdadbce0 OK |
411 | static const struct iio_info bma180_info = { |
412 | .attrs = &bma180_attrs_group, | |
413 | .read_raw = bma180_read_raw, | |
414 | .write_raw = bma180_write_raw, | |
fdadbce0 OK |
415 | .driver_module = THIS_MODULE, |
416 | }; | |
417 | ||
c7c69e85 | 418 | static const char * const bma180_power_modes[] = { "low_noise", "low_power" }; |
fdadbce0 OK |
419 | |
420 | static int bma180_get_power_mode(struct iio_dev *indio_dev, | |
421 | const struct iio_chan_spec *chan) | |
422 | { | |
423 | struct bma180_data *data = iio_priv(indio_dev); | |
424 | ||
425 | return data->pmode; | |
426 | } | |
427 | ||
428 | static int bma180_set_power_mode(struct iio_dev *indio_dev, | |
429 | const struct iio_chan_spec *chan, unsigned int mode) | |
430 | { | |
431 | struct bma180_data *data = iio_priv(indio_dev); | |
432 | int ret; | |
433 | ||
434 | mutex_lock(&data->mutex); | |
435 | ret = bma180_set_pmode(data, mode); | |
436 | mutex_unlock(&data->mutex); | |
437 | ||
438 | return ret; | |
439 | } | |
440 | ||
441 | static const struct iio_enum bma180_power_mode_enum = { | |
442 | .items = bma180_power_modes, | |
443 | .num_items = ARRAY_SIZE(bma180_power_modes), | |
444 | .get = bma180_get_power_mode, | |
445 | .set = bma180_set_power_mode, | |
446 | }; | |
447 | ||
448 | static const struct iio_chan_spec_ext_info bma180_ext_info[] = { | |
449 | IIO_ENUM("power_mode", true, &bma180_power_mode_enum), | |
450 | IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum), | |
451 | { }, | |
452 | }; | |
453 | ||
b81fbab7 | 454 | #define BMA180_ACC_CHANNEL(_axis) { \ |
fdadbce0 | 455 | .type = IIO_ACCEL, \ |
5585215b PM |
456 | .modified = 1, \ |
457 | .channel2 = IIO_MOD_##_axis, \ | |
5c1449d4 PM |
458 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
459 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
fdadbce0 | 460 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ |
5585215b | 461 | .scan_index = AXIS_##_axis, \ |
7d7feae7 JC |
462 | .scan_type = { \ |
463 | .sign = 's', \ | |
464 | .realbits = 14, \ | |
465 | .storagebits = 16, \ | |
466 | .shift = 2, \ | |
467 | }, \ | |
fdadbce0 OK |
468 | .ext_info = bma180_ext_info, \ |
469 | } | |
470 | ||
b81fbab7 PM |
471 | #define BMA180_TEMP_CHANNEL { \ |
472 | .type = IIO_TEMP, \ | |
473 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
474 | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \ | |
475 | .scan_index = TEMP, \ | |
476 | .scan_type = { \ | |
477 | .sign = 's', \ | |
478 | .realbits = 8, \ | |
479 | .storagebits = 16, \ | |
480 | }, \ | |
481 | } | |
482 | ||
fdadbce0 | 483 | static const struct iio_chan_spec bma180_channels[] = { |
b81fbab7 PM |
484 | BMA180_ACC_CHANNEL(X), |
485 | BMA180_ACC_CHANNEL(Y), | |
486 | BMA180_ACC_CHANNEL(Z), | |
487 | BMA180_TEMP_CHANNEL, | |
488 | IIO_CHAN_SOFT_TIMESTAMP(4), | |
fdadbce0 OK |
489 | }; |
490 | ||
491 | static irqreturn_t bma180_trigger_handler(int irq, void *p) | |
492 | { | |
493 | struct iio_poll_func *pf = p; | |
494 | struct iio_dev *indio_dev = pf->indio_dev; | |
495 | struct bma180_data *data = iio_priv(indio_dev); | |
6bf9d877 | 496 | int64_t time_ns = iio_get_time_ns(); |
fdadbce0 OK |
497 | int bit, ret, i = 0; |
498 | ||
499 | mutex_lock(&data->mutex); | |
fdadbce0 OK |
500 | |
501 | for_each_set_bit(bit, indio_dev->buffer->scan_mask, | |
502 | indio_dev->masklength) { | |
b81fbab7 | 503 | ret = bma180_get_data_reg(data, bit); |
fdadbce0 OK |
504 | if (ret < 0) { |
505 | mutex_unlock(&data->mutex); | |
506 | goto err; | |
507 | } | |
508 | ((s16 *)data->buff)[i++] = ret; | |
509 | } | |
b81fbab7 | 510 | |
fdadbce0 OK |
511 | mutex_unlock(&data->mutex); |
512 | ||
6bf9d877 | 513 | iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); |
fdadbce0 OK |
514 | err: |
515 | iio_trigger_notify_done(indio_dev->trig); | |
516 | ||
517 | return IRQ_HANDLED; | |
518 | } | |
519 | ||
520 | static int bma180_data_rdy_trigger_set_state(struct iio_trigger *trig, | |
521 | bool state) | |
522 | { | |
523 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | |
524 | struct bma180_data *data = iio_priv(indio_dev); | |
525 | ||
526 | return bma180_set_new_data_intr_state(data, state); | |
527 | } | |
528 | ||
529 | static int bma180_trig_try_reen(struct iio_trigger *trig) | |
530 | { | |
531 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | |
532 | struct bma180_data *data = iio_priv(indio_dev); | |
533 | ||
534 | return bma180_reset_intr(data); | |
535 | } | |
536 | ||
537 | static const struct iio_trigger_ops bma180_trigger_ops = { | |
538 | .set_trigger_state = bma180_data_rdy_trigger_set_state, | |
539 | .try_reenable = bma180_trig_try_reen, | |
540 | .owner = THIS_MODULE, | |
541 | }; | |
542 | ||
543 | static int bma180_probe(struct i2c_client *client, | |
544 | const struct i2c_device_id *id) | |
545 | { | |
546 | struct bma180_data *data; | |
547 | struct iio_dev *indio_dev; | |
fdadbce0 OK |
548 | int ret; |
549 | ||
550 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
551 | if (!indio_dev) | |
552 | return -ENOMEM; | |
553 | ||
554 | data = iio_priv(indio_dev); | |
555 | i2c_set_clientdata(client, indio_dev); | |
556 | data->client = client; | |
557 | ||
558 | ret = bma180_chip_init(data); | |
559 | if (ret < 0) | |
560 | goto err_chip_disable; | |
561 | ||
562 | mutex_init(&data->mutex); | |
563 | ||
564 | indio_dev->dev.parent = &client->dev; | |
565 | indio_dev->channels = bma180_channels; | |
566 | indio_dev->num_channels = ARRAY_SIZE(bma180_channels); | |
567 | indio_dev->name = BMA180_DRV_NAME; | |
568 | indio_dev->modes = INDIO_DIRECT_MODE; | |
569 | indio_dev->info = &bma180_info; | |
570 | ||
16ed8692 PM |
571 | if (client->irq > 0) { |
572 | data->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, | |
573 | indio_dev->id); | |
574 | if (!data->trig) { | |
575 | ret = -ENOMEM; | |
576 | goto err_chip_disable; | |
577 | } | |
fdadbce0 | 578 | |
16ed8692 PM |
579 | ret = devm_request_irq(&client->dev, client->irq, |
580 | iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, | |
581 | BMA180_IRQ_NAME, data->trig); | |
582 | if (ret) { | |
583 | dev_err(&client->dev, "unable to request IRQ\n"); | |
584 | goto err_trigger_free; | |
585 | } | |
fdadbce0 | 586 | |
16ed8692 PM |
587 | data->trig->dev.parent = &client->dev; |
588 | data->trig->ops = &bma180_trigger_ops; | |
589 | iio_trigger_set_drvdata(data->trig, indio_dev); | |
590 | indio_dev->trig = data->trig; | |
fdadbce0 | 591 | |
16ed8692 PM |
592 | ret = iio_trigger_register(data->trig); |
593 | if (ret) | |
594 | goto err_trigger_free; | |
595 | } | |
fdadbce0 OK |
596 | |
597 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | |
598 | bma180_trigger_handler, NULL); | |
599 | if (ret < 0) { | |
600 | dev_err(&client->dev, "unable to setup iio triggered buffer\n"); | |
601 | goto err_trigger_unregister; | |
602 | } | |
603 | ||
604 | ret = iio_device_register(indio_dev); | |
605 | if (ret < 0) { | |
606 | dev_err(&client->dev, "unable to register iio device\n"); | |
607 | goto err_buffer_cleanup; | |
608 | } | |
609 | ||
610 | return 0; | |
611 | ||
612 | err_buffer_cleanup: | |
613 | iio_triggered_buffer_cleanup(indio_dev); | |
614 | err_trigger_unregister: | |
16ed8692 PM |
615 | if (data->trig) |
616 | iio_trigger_unregister(data->trig); | |
fdadbce0 | 617 | err_trigger_free: |
16ed8692 | 618 | iio_trigger_free(data->trig); |
fdadbce0 OK |
619 | err_chip_disable: |
620 | bma180_chip_disable(data); | |
621 | ||
622 | return ret; | |
623 | } | |
624 | ||
625 | static int bma180_remove(struct i2c_client *client) | |
626 | { | |
627 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
628 | struct bma180_data *data = iio_priv(indio_dev); | |
629 | ||
630 | iio_device_unregister(indio_dev); | |
631 | iio_triggered_buffer_cleanup(indio_dev); | |
16ed8692 PM |
632 | if (data->trig) { |
633 | iio_trigger_unregister(data->trig); | |
634 | iio_trigger_free(data->trig); | |
635 | } | |
fdadbce0 OK |
636 | |
637 | mutex_lock(&data->mutex); | |
638 | bma180_chip_disable(data); | |
639 | mutex_unlock(&data->mutex); | |
640 | ||
641 | return 0; | |
642 | } | |
643 | ||
644 | #ifdef CONFIG_PM_SLEEP | |
645 | static int bma180_suspend(struct device *dev) | |
646 | { | |
234efa17 | 647 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
fdadbce0 OK |
648 | struct bma180_data *data = iio_priv(indio_dev); |
649 | int ret; | |
650 | ||
651 | mutex_lock(&data->mutex); | |
c7c69e85 | 652 | ret = bma180_set_sleep_state(data, true); |
fdadbce0 OK |
653 | mutex_unlock(&data->mutex); |
654 | ||
655 | return ret; | |
656 | } | |
657 | ||
658 | static int bma180_resume(struct device *dev) | |
659 | { | |
234efa17 | 660 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
fdadbce0 OK |
661 | struct bma180_data *data = iio_priv(indio_dev); |
662 | int ret; | |
663 | ||
664 | mutex_lock(&data->mutex); | |
c7c69e85 | 665 | ret = bma180_set_sleep_state(data, false); |
fdadbce0 OK |
666 | mutex_unlock(&data->mutex); |
667 | ||
668 | return ret; | |
669 | } | |
670 | ||
671 | static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); | |
672 | #define BMA180_PM_OPS (&bma180_pm_ops) | |
673 | #else | |
674 | #define BMA180_PM_OPS NULL | |
675 | #endif | |
676 | ||
677 | static struct i2c_device_id bma180_id[] = { | |
678 | { BMA180_DRV_NAME, 0 }, | |
679 | { } | |
680 | }; | |
681 | ||
682 | MODULE_DEVICE_TABLE(i2c, bma180_id); | |
683 | ||
684 | static struct i2c_driver bma180_driver = { | |
685 | .driver = { | |
686 | .name = BMA180_DRV_NAME, | |
687 | .owner = THIS_MODULE, | |
688 | .pm = BMA180_PM_OPS, | |
689 | }, | |
690 | .probe = bma180_probe, | |
691 | .remove = bma180_remove, | |
692 | .id_table = bma180_id, | |
693 | }; | |
694 | ||
695 | module_i2c_driver(bma180_driver); | |
696 | ||
697 | MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>"); | |
698 | MODULE_AUTHOR("Texas Instruments, Inc."); | |
699 | MODULE_DESCRIPTION("Bosch BMA180 triaxial acceleration sensor"); | |
700 | MODULE_LICENSE("GPL"); |