1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2011 Bosch Sensortec GmbH |
4 | * Copyright (c) 2011 Unixphere |
5 | * |
6 | * This driver adds support for Bosch Sensortec's digital acceleration |
7 | * sensors BMA150 and SMB380. |
8 | * The SMB380 is fully compatible with BMA150 and only differs in packaging. |
9 | * |
10 | * The datasheet for the BMA150 chip can be found here: |
11 | * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf |
12 | */ |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/i2c.h> |
16 | #include <linux/input.h> |
17 | #include <linux/interrupt.h> |
18 | #include <linux/delay.h> |
19 | #include <linux/slab.h> |
20 | #include <linux/pm.h> |
21 | #include <linux/pm_runtime.h> |
22 | #include <linux/bma150.h> |
23 | |
24 | #define ABSMAX_ACC_VAL 0x01FF |
25 | #define ABSMIN_ACC_VAL -(ABSMAX_ACC_VAL) |
26 | |
27 | /* Each axis is represented by a 2-byte data word */ |
28 | #define BMA150_XYZ_DATA_SIZE 6 |
29 | |
30 | /* Input poll interval in milliseconds */ |
31 | #define BMA150_POLL_INTERVAL 10 |
32 | #define BMA150_POLL_MAX 200 |
33 | #define BMA150_POLL_MIN 0 |
34 | |
35 | #define BMA150_MODE_NORMAL 0 |
36 | #define BMA150_MODE_SLEEP 2 |
37 | #define BMA150_MODE_WAKE_UP 3 |
38 | |
39 | /* Data register addresses */ |
40 | #define BMA150_DATA_0_REG 0x00 |
41 | #define BMA150_DATA_1_REG 0x01 |
42 | #define BMA150_DATA_2_REG 0x02 |
43 | |
44 | /* Control register addresses */ |
45 | #define BMA150_CTRL_0_REG 0x0A |
46 | #define BMA150_CTRL_1_REG 0x0B |
47 | #define BMA150_CTRL_2_REG 0x14 |
48 | #define BMA150_CTRL_3_REG 0x15 |
49 | |
50 | /* Configuration/Setting register addresses */ |
51 | #define BMA150_CFG_0_REG 0x0C |
52 | #define BMA150_CFG_1_REG 0x0D |
53 | #define BMA150_CFG_2_REG 0x0E |
54 | #define BMA150_CFG_3_REG 0x0F |
55 | #define BMA150_CFG_4_REG 0x10 |
56 | #define BMA150_CFG_5_REG 0x11 |
57 | |
58 | #define BMA150_CHIP_ID 2 |
59 | #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG |
60 | |
61 | #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG |
62 | |
63 | #define BMA150_SLEEP_POS 0 |
64 | #define BMA150_SLEEP_MSK 0x01 |
65 | #define BMA150_SLEEP_REG BMA150_CTRL_0_REG |
66 | |
67 | #define BMA150_BANDWIDTH_POS 0 |
68 | #define BMA150_BANDWIDTH_MSK 0x07 |
69 | #define BMA150_BANDWIDTH_REG BMA150_CTRL_2_REG |
70 | |
71 | #define BMA150_RANGE_POS 3 |
72 | #define BMA150_RANGE_MSK 0x18 |
73 | #define BMA150_RANGE_REG BMA150_CTRL_2_REG |
74 | |
75 | #define BMA150_WAKE_UP_POS 0 |
76 | #define BMA150_WAKE_UP_MSK 0x01 |
77 | #define BMA150_WAKE_UP_REG BMA150_CTRL_3_REG |
78 | |
79 | #define BMA150_SW_RES_POS 1 |
80 | #define BMA150_SW_RES_MSK 0x02 |
81 | #define BMA150_SW_RES_REG BMA150_CTRL_0_REG |
82 | |
83 | /* Any-motion interrupt register fields */ |
84 | #define BMA150_ANY_MOTION_EN_POS 6 |
85 | #define BMA150_ANY_MOTION_EN_MSK 0x40 |
86 | #define BMA150_ANY_MOTION_EN_REG BMA150_CTRL_1_REG |
87 | |
88 | #define BMA150_ANY_MOTION_DUR_POS 6 |
89 | #define BMA150_ANY_MOTION_DUR_MSK 0xC0 |
90 | #define BMA150_ANY_MOTION_DUR_REG BMA150_CFG_5_REG |
91 | |
92 | #define BMA150_ANY_MOTION_THRES_REG BMA150_CFG_4_REG |
93 | |
94 | /* Advanced interrupt register fields */ |
95 | #define BMA150_ADV_INT_EN_POS 6 |
96 | #define BMA150_ADV_INT_EN_MSK 0x40 |
97 | #define BMA150_ADV_INT_EN_REG BMA150_CTRL_3_REG |
98 | |
99 | /* High-G interrupt register fields */ |
100 | #define BMA150_HIGH_G_EN_POS 1 |
101 | #define BMA150_HIGH_G_EN_MSK 0x02 |
102 | #define BMA150_HIGH_G_EN_REG BMA150_CTRL_1_REG |
103 | |
104 | #define BMA150_HIGH_G_HYST_POS 3 |
105 | #define BMA150_HIGH_G_HYST_MSK 0x38 |
106 | #define BMA150_HIGH_G_HYST_REG BMA150_CFG_5_REG |
107 | |
108 | #define BMA150_HIGH_G_DUR_REG BMA150_CFG_3_REG |
109 | #define BMA150_HIGH_G_THRES_REG BMA150_CFG_2_REG |
110 | |
111 | /* Low-G interrupt register fields */ |
112 | #define BMA150_LOW_G_EN_POS 0 |
113 | #define BMA150_LOW_G_EN_MSK 0x01 |
114 | #define BMA150_LOW_G_EN_REG BMA150_CTRL_1_REG |
115 | |
116 | #define BMA150_LOW_G_HYST_POS 0 |
117 | #define BMA150_LOW_G_HYST_MSK 0x07 |
118 | #define BMA150_LOW_G_HYST_REG BMA150_CFG_5_REG |
119 | |
120 | #define BMA150_LOW_G_DUR_REG BMA150_CFG_1_REG |
121 | #define BMA150_LOW_G_THRES_REG BMA150_CFG_0_REG |
122 | |
123 | struct bma150_data { |
124 | struct i2c_client *client; |
125 | struct input_dev *input; |
126 | u8 mode; |
127 | }; |
128 | |
129 | /* |
130 | * The settings for the given range, bandwidth and interrupt features |
131 | * are stated and verified by Bosch Sensortec where they are configured |
132 | * to provide a generic sensitivity performance. |
133 | */ |
134 | static const struct bma150_cfg default_cfg = { |
135 | .any_motion_int = 1, |
136 | .hg_int = 1, |
137 | .lg_int = 1, |
138 | .any_motion_dur = 0, |
139 | .any_motion_thres = 0, |
140 | .hg_hyst = 0, |
141 | .hg_dur = 150, |
142 | .hg_thres = 160, |
143 | .lg_hyst = 0, |
144 | .lg_dur = 150, |
145 | .lg_thres = 20, |
146 | .range = BMA150_RANGE_2G, |
147 | .bandwidth = BMA150_BW_50HZ |
148 | }; |
149 | |
150 | static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val) |
151 | { |
152 | s32 ret; |
153 | |
154 | /* As per specification, disable irq in between register writes */ |
155 | if (client->irq) |
156 | disable_irq_nosync(irq: client->irq); |
157 | |
158 | ret = i2c_smbus_write_byte_data(client, command: reg, value: val); |
159 | |
160 | if (client->irq) |
161 | enable_irq(irq: client->irq); |
162 | |
163 | return ret; |
164 | } |
165 | |
166 | static int bma150_set_reg_bits(struct i2c_client *client, |
167 | int val, int shift, u8 mask, u8 reg) |
168 | { |
169 | int data; |
170 | |
171 | data = i2c_smbus_read_byte_data(client, command: reg); |
172 | if (data < 0) |
173 | return data; |
174 | |
175 | data = (data & ~mask) | ((val << shift) & mask); |
176 | return bma150_write_byte(client, reg, val: data); |
177 | } |
178 | |
179 | static int bma150_set_mode(struct bma150_data *bma150, u8 mode) |
180 | { |
181 | int error; |
182 | |
183 | error = bma150_set_reg_bits(client: bma150->client, val: mode, BMA150_WAKE_UP_POS, |
184 | BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG); |
185 | if (error) |
186 | return error; |
187 | |
188 | error = bma150_set_reg_bits(client: bma150->client, val: mode, BMA150_SLEEP_POS, |
189 | BMA150_SLEEP_MSK, BMA150_SLEEP_REG); |
190 | if (error) |
191 | return error; |
192 | |
193 | if (mode == BMA150_MODE_NORMAL) |
194 | usleep_range(min: 2000, max: 2100); |
195 | |
196 | bma150->mode = mode; |
197 | return 0; |
198 | } |
199 | |
200 | static int bma150_soft_reset(struct bma150_data *bma150) |
201 | { |
202 | int error; |
203 | |
204 | error = bma150_set_reg_bits(client: bma150->client, val: 1, BMA150_SW_RES_POS, |
205 | BMA150_SW_RES_MSK, BMA150_SW_RES_REG); |
206 | if (error) |
207 | return error; |
208 | |
209 | usleep_range(min: 2000, max: 2100); |
210 | return 0; |
211 | } |
212 | |
213 | static int bma150_set_range(struct bma150_data *bma150, u8 range) |
214 | { |
215 | return bma150_set_reg_bits(client: bma150->client, val: range, BMA150_RANGE_POS, |
216 | BMA150_RANGE_MSK, BMA150_RANGE_REG); |
217 | } |
218 | |
219 | static int bma150_set_bandwidth(struct bma150_data *bma150, u8 bw) |
220 | { |
221 | return bma150_set_reg_bits(client: bma150->client, val: bw, BMA150_BANDWIDTH_POS, |
222 | BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG); |
223 | } |
224 | |
225 | static int bma150_set_low_g_interrupt(struct bma150_data *bma150, |
226 | u8 enable, u8 hyst, u8 dur, u8 thres) |
227 | { |
228 | int error; |
229 | |
230 | error = bma150_set_reg_bits(client: bma150->client, val: hyst, |
231 | BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK, |
232 | BMA150_LOW_G_HYST_REG); |
233 | if (error) |
234 | return error; |
235 | |
236 | error = bma150_write_byte(client: bma150->client, BMA150_LOW_G_DUR_REG, val: dur); |
237 | if (error) |
238 | return error; |
239 | |
240 | error = bma150_write_byte(client: bma150->client, BMA150_LOW_G_THRES_REG, val: thres); |
241 | if (error) |
242 | return error; |
243 | |
244 | return bma150_set_reg_bits(client: bma150->client, val: !!enable, |
245 | BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK, |
246 | BMA150_LOW_G_EN_REG); |
247 | } |
248 | |
249 | static int bma150_set_high_g_interrupt(struct bma150_data *bma150, |
250 | u8 enable, u8 hyst, u8 dur, u8 thres) |
251 | { |
252 | int error; |
253 | |
254 | error = bma150_set_reg_bits(client: bma150->client, val: hyst, |
255 | BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK, |
256 | BMA150_HIGH_G_HYST_REG); |
257 | if (error) |
258 | return error; |
259 | |
260 | error = bma150_write_byte(client: bma150->client, |
261 | BMA150_HIGH_G_DUR_REG, val: dur); |
262 | if (error) |
263 | return error; |
264 | |
265 | error = bma150_write_byte(client: bma150->client, |
266 | BMA150_HIGH_G_THRES_REG, val: thres); |
267 | if (error) |
268 | return error; |
269 | |
270 | return bma150_set_reg_bits(client: bma150->client, val: !!enable, |
271 | BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK, |
272 | BMA150_HIGH_G_EN_REG); |
273 | } |
274 | |
275 | |
276 | static int bma150_set_any_motion_interrupt(struct bma150_data *bma150, |
277 | u8 enable, u8 dur, u8 thres) |
278 | { |
279 | int error; |
280 | |
281 | error = bma150_set_reg_bits(client: bma150->client, val: dur, |
282 | BMA150_ANY_MOTION_DUR_POS, |
283 | BMA150_ANY_MOTION_DUR_MSK, |
284 | BMA150_ANY_MOTION_DUR_REG); |
285 | if (error) |
286 | return error; |
287 | |
288 | error = bma150_write_byte(client: bma150->client, |
289 | BMA150_ANY_MOTION_THRES_REG, val: thres); |
290 | if (error) |
291 | return error; |
292 | |
293 | error = bma150_set_reg_bits(client: bma150->client, val: !!enable, |
294 | BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK, |
295 | BMA150_ADV_INT_EN_REG); |
296 | if (error) |
297 | return error; |
298 | |
299 | return bma150_set_reg_bits(client: bma150->client, val: !!enable, |
300 | BMA150_ANY_MOTION_EN_POS, |
301 | BMA150_ANY_MOTION_EN_MSK, |
302 | BMA150_ANY_MOTION_EN_REG); |
303 | } |
304 | |
305 | static void bma150_report_xyz(struct bma150_data *bma150) |
306 | { |
307 | u8 data[BMA150_XYZ_DATA_SIZE]; |
308 | s16 x, y, z; |
309 | s32 ret; |
310 | |
311 | ret = i2c_smbus_read_i2c_block_data(client: bma150->client, |
312 | BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, values: data); |
313 | if (ret != BMA150_XYZ_DATA_SIZE) |
314 | return; |
315 | |
316 | x = ((0xc0 & data[0]) >> 6) | (data[1] << 2); |
317 | y = ((0xc0 & data[2]) >> 6) | (data[3] << 2); |
318 | z = ((0xc0 & data[4]) >> 6) | (data[5] << 2); |
319 | |
320 | x = sign_extend32(value: x, index: 9); |
321 | y = sign_extend32(value: y, index: 9); |
322 | z = sign_extend32(value: z, index: 9); |
323 | |
324 | input_report_abs(dev: bma150->input, ABS_X, value: x); |
325 | input_report_abs(dev: bma150->input, ABS_Y, value: y); |
326 | input_report_abs(dev: bma150->input, ABS_Z, value: z); |
327 | input_sync(dev: bma150->input); |
328 | } |
329 | |
330 | static irqreturn_t bma150_irq_thread(int irq, void *dev) |
331 | { |
332 | bma150_report_xyz(bma150: dev); |
333 | |
334 | return IRQ_HANDLED; |
335 | } |
336 | |
337 | static void bma150_poll(struct input_dev *input) |
338 | { |
339 | struct bma150_data *bma150 = input_get_drvdata(dev: input); |
340 | |
341 | bma150_report_xyz(bma150); |
342 | } |
343 | |
344 | static int bma150_open(struct input_dev *input) |
345 | { |
346 | struct bma150_data *bma150 = input_get_drvdata(dev: input); |
347 | int error; |
348 | |
349 | error = pm_runtime_get_sync(dev: &bma150->client->dev); |
350 | if (error < 0 && error != -ENOSYS) |
351 | return error; |
352 | |
353 | /* |
354 | * See if runtime PM woke up the device. If runtime PM |
355 | * is disabled we need to do it ourselves. |
356 | */ |
357 | if (bma150->mode != BMA150_MODE_NORMAL) { |
358 | error = bma150_set_mode(bma150, BMA150_MODE_NORMAL); |
359 | if (error) |
360 | return error; |
361 | } |
362 | |
363 | return 0; |
364 | } |
365 | |
366 | static void bma150_close(struct input_dev *input) |
367 | { |
368 | struct bma150_data *bma150 = input_get_drvdata(dev: input); |
369 | |
370 | pm_runtime_put_sync(dev: &bma150->client->dev); |
371 | |
372 | if (bma150->mode != BMA150_MODE_SLEEP) |
373 | bma150_set_mode(bma150, BMA150_MODE_SLEEP); |
374 | } |
375 | |
376 | static int bma150_initialize(struct bma150_data *bma150, |
377 | const struct bma150_cfg *cfg) |
378 | { |
379 | int error; |
380 | |
381 | error = bma150_soft_reset(bma150); |
382 | if (error) |
383 | return error; |
384 | |
385 | error = bma150_set_bandwidth(bma150, bw: cfg->bandwidth); |
386 | if (error) |
387 | return error; |
388 | |
389 | error = bma150_set_range(bma150, range: cfg->range); |
390 | if (error) |
391 | return error; |
392 | |
393 | if (bma150->client->irq) { |
394 | error = bma150_set_any_motion_interrupt(bma150, |
395 | enable: cfg->any_motion_int, |
396 | dur: cfg->any_motion_dur, |
397 | thres: cfg->any_motion_thres); |
398 | if (error) |
399 | return error; |
400 | |
401 | error = bma150_set_high_g_interrupt(bma150, |
402 | enable: cfg->hg_int, hyst: cfg->hg_hyst, |
403 | dur: cfg->hg_dur, thres: cfg->hg_thres); |
404 | if (error) |
405 | return error; |
406 | |
407 | error = bma150_set_low_g_interrupt(bma150, |
408 | enable: cfg->lg_int, hyst: cfg->lg_hyst, |
409 | dur: cfg->lg_dur, thres: cfg->lg_thres); |
410 | if (error) |
411 | return error; |
412 | } |
413 | |
414 | return bma150_set_mode(bma150, BMA150_MODE_SLEEP); |
415 | } |
416 | |
417 | static int bma150_probe(struct i2c_client *client) |
418 | { |
419 | const struct bma150_platform_data *pdata = |
420 | dev_get_platdata(dev: &client->dev); |
421 | const struct bma150_cfg *cfg; |
422 | struct bma150_data *bma150; |
423 | struct input_dev *idev; |
424 | int chip_id; |
425 | int error; |
426 | |
427 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
428 | dev_err(&client->dev, "i2c_check_functionality error\n" ); |
429 | return -EIO; |
430 | } |
431 | |
432 | chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); |
433 | if (chip_id != BMA150_CHIP_ID) { |
434 | dev_err(&client->dev, "BMA150 chip id error: %d\n" , chip_id); |
435 | return -EINVAL; |
436 | } |
437 | |
438 | bma150 = devm_kzalloc(dev: &client->dev, size: sizeof(*bma150), GFP_KERNEL); |
439 | if (!bma150) |
440 | return -ENOMEM; |
441 | |
442 | bma150->client = client; |
443 | |
444 | if (pdata) { |
445 | if (pdata->irq_gpio_cfg) { |
446 | error = pdata->irq_gpio_cfg(); |
447 | if (error) { |
448 | dev_err(&client->dev, |
449 | "IRQ GPIO conf. error %d, error %d\n" , |
450 | client->irq, error); |
451 | return error; |
452 | } |
453 | } |
454 | cfg = &pdata->cfg; |
455 | } else { |
456 | cfg = &default_cfg; |
457 | } |
458 | |
459 | error = bma150_initialize(bma150, cfg); |
460 | if (error) |
461 | return error; |
462 | |
463 | idev = devm_input_allocate_device(&bma150->client->dev); |
464 | if (!idev) |
465 | return -ENOMEM; |
466 | |
467 | input_set_drvdata(dev: idev, data: bma150); |
468 | bma150->input = idev; |
469 | |
470 | idev->name = BMA150_DRIVER; |
471 | idev->phys = BMA150_DRIVER "/input0" ; |
472 | idev->id.bustype = BUS_I2C; |
473 | |
474 | idev->open = bma150_open; |
475 | idev->close = bma150_close; |
476 | |
477 | input_set_abs_params(dev: idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, fuzz: 0, flat: 0); |
478 | input_set_abs_params(dev: idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, fuzz: 0, flat: 0); |
479 | input_set_abs_params(dev: idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, fuzz: 0, flat: 0); |
480 | |
481 | if (client->irq <= 0) { |
482 | error = input_setup_polling(dev: idev, poll_fn: bma150_poll); |
483 | if (error) |
484 | return error; |
485 | |
486 | input_set_poll_interval(dev: idev, BMA150_POLL_INTERVAL); |
487 | input_set_min_poll_interval(dev: idev, BMA150_POLL_MIN); |
488 | input_set_max_poll_interval(dev: idev, BMA150_POLL_MAX); |
489 | } |
490 | |
491 | error = input_register_device(idev); |
492 | if (error) |
493 | return error; |
494 | |
495 | if (client->irq > 0) { |
496 | error = devm_request_threaded_irq(dev: &client->dev, irq: client->irq, |
497 | NULL, thread_fn: bma150_irq_thread, |
498 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
499 | BMA150_DRIVER, dev_id: bma150); |
500 | if (error) { |
501 | dev_err(&client->dev, |
502 | "irq request failed %d, error %d\n" , |
503 | client->irq, error); |
504 | return error; |
505 | } |
506 | } |
507 | |
508 | i2c_set_clientdata(client, data: bma150); |
509 | |
510 | pm_runtime_enable(dev: &client->dev); |
511 | |
512 | return 0; |
513 | } |
514 | |
515 | static void bma150_remove(struct i2c_client *client) |
516 | { |
517 | pm_runtime_disable(dev: &client->dev); |
518 | } |
519 | |
520 | static int __maybe_unused bma150_suspend(struct device *dev) |
521 | { |
522 | struct i2c_client *client = to_i2c_client(dev); |
523 | struct bma150_data *bma150 = i2c_get_clientdata(client); |
524 | |
525 | return bma150_set_mode(bma150, BMA150_MODE_SLEEP); |
526 | } |
527 | |
528 | static int __maybe_unused bma150_resume(struct device *dev) |
529 | { |
530 | struct i2c_client *client = to_i2c_client(dev); |
531 | struct bma150_data *bma150 = i2c_get_clientdata(client); |
532 | |
533 | return bma150_set_mode(bma150, BMA150_MODE_NORMAL); |
534 | } |
535 | |
536 | static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); |
537 | |
538 | static const struct i2c_device_id bma150_id[] = { |
539 | { "bma150" , 0 }, |
540 | { "smb380" , 0 }, |
541 | { "bma023" , 0 }, |
542 | { } |
543 | }; |
544 | |
545 | MODULE_DEVICE_TABLE(i2c, bma150_id); |
546 | |
547 | static struct i2c_driver bma150_driver = { |
548 | .driver = { |
549 | .name = BMA150_DRIVER, |
550 | .pm = &bma150_pm, |
551 | }, |
552 | .class = I2C_CLASS_HWMON, |
553 | .id_table = bma150_id, |
554 | .probe = bma150_probe, |
555 | .remove = bma150_remove, |
556 | }; |
557 | |
558 | module_i2c_driver(bma150_driver); |
559 | |
560 | MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>" ); |
561 | MODULE_DESCRIPTION("BMA150 driver" ); |
562 | MODULE_LICENSE("GPL" ); |
563 | |