1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * ADXL345/346 Three-Axis Digital Accelerometers |
4 | * |
5 | * Enter bugs at http://blackfin.uclinux.org/ |
6 | * |
7 | * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/input.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/irq.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/workqueue.h> |
17 | #include <linux/input/adxl34x.h> |
18 | #include <linux/module.h> |
19 | |
20 | #include "adxl34x.h" |
21 | |
22 | /* ADXL345/6 Register Map */ |
23 | #define DEVID 0x00 /* R Device ID */ |
24 | #define THRESH_TAP 0x1D /* R/W Tap threshold */ |
25 | #define OFSX 0x1E /* R/W X-axis offset */ |
26 | #define OFSY 0x1F /* R/W Y-axis offset */ |
27 | #define OFSZ 0x20 /* R/W Z-axis offset */ |
28 | #define DUR 0x21 /* R/W Tap duration */ |
29 | #define LATENT 0x22 /* R/W Tap latency */ |
30 | #define WINDOW 0x23 /* R/W Tap window */ |
31 | #define THRESH_ACT 0x24 /* R/W Activity threshold */ |
32 | #define THRESH_INACT 0x25 /* R/W Inactivity threshold */ |
33 | #define TIME_INACT 0x26 /* R/W Inactivity time */ |
34 | #define ACT_INACT_CTL 0x27 /* R/W Axis enable control for activity and */ |
35 | /* inactivity detection */ |
36 | #define THRESH_FF 0x28 /* R/W Free-fall threshold */ |
37 | #define TIME_FF 0x29 /* R/W Free-fall time */ |
38 | #define TAP_AXES 0x2A /* R/W Axis control for tap/double tap */ |
39 | #define ACT_TAP_STATUS 0x2B /* R Source of tap/double tap */ |
40 | #define BW_RATE 0x2C /* R/W Data rate and power mode control */ |
41 | #define POWER_CTL 0x2D /* R/W Power saving features control */ |
42 | #define INT_ENABLE 0x2E /* R/W Interrupt enable control */ |
43 | #define INT_MAP 0x2F /* R/W Interrupt mapping control */ |
44 | #define INT_SOURCE 0x30 /* R Source of interrupts */ |
45 | #define DATA_FORMAT 0x31 /* R/W Data format control */ |
46 | #define DATAX0 0x32 /* R X-Axis Data 0 */ |
47 | #define DATAX1 0x33 /* R X-Axis Data 1 */ |
48 | #define DATAY0 0x34 /* R Y-Axis Data 0 */ |
49 | #define DATAY1 0x35 /* R Y-Axis Data 1 */ |
50 | #define DATAZ0 0x36 /* R Z-Axis Data 0 */ |
51 | #define DATAZ1 0x37 /* R Z-Axis Data 1 */ |
52 | #define FIFO_CTL 0x38 /* R/W FIFO control */ |
53 | #define FIFO_STATUS 0x39 /* R FIFO status */ |
54 | #define TAP_SIGN 0x3A /* R Sign and source for tap/double tap */ |
55 | /* Orientation ADXL346 only */ |
56 | #define ORIENT_CONF 0x3B /* R/W Orientation configuration */ |
57 | #define ORIENT 0x3C /* R Orientation status */ |
58 | |
59 | /* DEVIDs */ |
60 | #define ID_ADXL345 0xE5 |
61 | #define ID_ADXL346 0xE6 |
62 | |
63 | /* INT_ENABLE/INT_MAP/INT_SOURCE Bits */ |
64 | #define DATA_READY (1 << 7) |
65 | #define SINGLE_TAP (1 << 6) |
66 | #define DOUBLE_TAP (1 << 5) |
67 | #define ACTIVITY (1 << 4) |
68 | #define INACTIVITY (1 << 3) |
69 | #define FREE_FALL (1 << 2) |
70 | #define WATERMARK (1 << 1) |
71 | #define OVERRUN (1 << 0) |
72 | |
73 | /* ACT_INACT_CONTROL Bits */ |
74 | #define ACT_ACDC (1 << 7) |
75 | #define ACT_X_EN (1 << 6) |
76 | #define ACT_Y_EN (1 << 5) |
77 | #define ACT_Z_EN (1 << 4) |
78 | #define INACT_ACDC (1 << 3) |
79 | #define INACT_X_EN (1 << 2) |
80 | #define INACT_Y_EN (1 << 1) |
81 | #define INACT_Z_EN (1 << 0) |
82 | |
83 | /* TAP_AXES Bits */ |
84 | #define SUPPRESS (1 << 3) |
85 | #define TAP_X_EN (1 << 2) |
86 | #define TAP_Y_EN (1 << 1) |
87 | #define TAP_Z_EN (1 << 0) |
88 | |
89 | /* ACT_TAP_STATUS Bits */ |
90 | #define ACT_X_SRC (1 << 6) |
91 | #define ACT_Y_SRC (1 << 5) |
92 | #define ACT_Z_SRC (1 << 4) |
93 | #define ASLEEP (1 << 3) |
94 | #define TAP_X_SRC (1 << 2) |
95 | #define TAP_Y_SRC (1 << 1) |
96 | #define TAP_Z_SRC (1 << 0) |
97 | |
98 | /* BW_RATE Bits */ |
99 | #define LOW_POWER (1 << 4) |
100 | #define RATE(x) ((x) & 0xF) |
101 | |
102 | /* POWER_CTL Bits */ |
103 | #define PCTL_LINK (1 << 5) |
104 | #define PCTL_AUTO_SLEEP (1 << 4) |
105 | #define PCTL_MEASURE (1 << 3) |
106 | #define PCTL_SLEEP (1 << 2) |
107 | #define PCTL_WAKEUP(x) ((x) & 0x3) |
108 | |
109 | /* DATA_FORMAT Bits */ |
110 | #define SELF_TEST (1 << 7) |
111 | #define SPI (1 << 6) |
112 | #define INT_INVERT (1 << 5) |
113 | #define FULL_RES (1 << 3) |
114 | #define JUSTIFY (1 << 2) |
115 | #define RANGE(x) ((x) & 0x3) |
116 | #define RANGE_PM_2g 0 |
117 | #define RANGE_PM_4g 1 |
118 | #define RANGE_PM_8g 2 |
119 | #define RANGE_PM_16g 3 |
120 | |
121 | /* |
122 | * Maximum value our axis may get in full res mode for the input device |
123 | * (signed 13 bits) |
124 | */ |
125 | #define ADXL_FULLRES_MAX_VAL 4096 |
126 | |
127 | /* |
128 | * Maximum value our axis may get in fixed res mode for the input device |
129 | * (signed 10 bits) |
130 | */ |
131 | #define ADXL_FIXEDRES_MAX_VAL 512 |
132 | |
133 | /* FIFO_CTL Bits */ |
134 | #define FIFO_MODE(x) (((x) & 0x3) << 6) |
135 | #define FIFO_BYPASS 0 |
136 | #define FIFO_FIFO 1 |
137 | #define FIFO_STREAM 2 |
138 | #define FIFO_TRIGGER 3 |
139 | #define TRIGGER (1 << 5) |
140 | #define SAMPLES(x) ((x) & 0x1F) |
141 | |
142 | /* FIFO_STATUS Bits */ |
143 | #define FIFO_TRIG (1 << 7) |
144 | #define ENTRIES(x) ((x) & 0x3F) |
145 | |
146 | /* TAP_SIGN Bits ADXL346 only */ |
147 | #define XSIGN (1 << 6) |
148 | #define YSIGN (1 << 5) |
149 | #define ZSIGN (1 << 4) |
150 | #define XTAP (1 << 3) |
151 | #define YTAP (1 << 2) |
152 | #define ZTAP (1 << 1) |
153 | |
154 | /* ORIENT_CONF ADXL346 only */ |
155 | #define ORIENT_DEADZONE(x) (((x) & 0x7) << 4) |
156 | #define ORIENT_DIVISOR(x) ((x) & 0x7) |
157 | |
158 | /* ORIENT ADXL346 only */ |
159 | #define ADXL346_2D_VALID (1 << 6) |
160 | #define ADXL346_2D_ORIENT(x) (((x) & 0x30) >> 4) |
161 | #define ADXL346_3D_VALID (1 << 3) |
162 | #define ADXL346_3D_ORIENT(x) ((x) & 0x7) |
163 | #define ADXL346_2D_PORTRAIT_POS 0 /* +X */ |
164 | #define ADXL346_2D_PORTRAIT_NEG 1 /* -X */ |
165 | #define ADXL346_2D_LANDSCAPE_POS 2 /* +Y */ |
166 | #define ADXL346_2D_LANDSCAPE_NEG 3 /* -Y */ |
167 | |
168 | #define ADXL346_3D_FRONT 3 /* +X */ |
169 | #define ADXL346_3D_BACK 4 /* -X */ |
170 | #define ADXL346_3D_RIGHT 2 /* +Y */ |
171 | #define ADXL346_3D_LEFT 5 /* -Y */ |
172 | #define ADXL346_3D_TOP 1 /* +Z */ |
173 | #define ADXL346_3D_BOTTOM 6 /* -Z */ |
174 | |
175 | #undef ADXL_DEBUG |
176 | |
177 | #define ADXL_X_AXIS 0 |
178 | #define ADXL_Y_AXIS 1 |
179 | #define ADXL_Z_AXIS 2 |
180 | |
181 | #define AC_READ(ac, reg) ((ac)->bops->read((ac)->dev, reg)) |
182 | #define AC_WRITE(ac, reg, val) ((ac)->bops->write((ac)->dev, reg, val)) |
183 | |
184 | struct axis_triple { |
185 | int x; |
186 | int y; |
187 | int z; |
188 | }; |
189 | |
190 | struct adxl34x { |
191 | struct device *dev; |
192 | struct input_dev *input; |
193 | struct mutex mutex; /* reentrant protection for struct */ |
194 | struct adxl34x_platform_data pdata; |
195 | struct axis_triple swcal; |
196 | struct axis_triple hwcal; |
197 | struct axis_triple saved; |
198 | char phys[32]; |
199 | unsigned orient2d_saved; |
200 | unsigned orient3d_saved; |
201 | bool disabled; /* P: mutex */ |
202 | bool opened; /* P: mutex */ |
203 | bool suspended; /* P: mutex */ |
204 | bool fifo_delay; |
205 | int irq; |
206 | unsigned model; |
207 | unsigned int_mask; |
208 | |
209 | const struct adxl34x_bus_ops *bops; |
210 | }; |
211 | |
212 | static const struct adxl34x_platform_data adxl34x_default_init = { |
213 | .tap_threshold = 35, |
214 | .tap_duration = 3, |
215 | .tap_latency = 20, |
216 | .tap_window = 20, |
217 | .tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN, |
218 | .act_axis_control = 0xFF, |
219 | .activity_threshold = 6, |
220 | .inactivity_threshold = 4, |
221 | .inactivity_time = 3, |
222 | .free_fall_threshold = 8, |
223 | .free_fall_time = 0x20, |
224 | .data_rate = 8, |
225 | .data_range = ADXL_FULL_RES, |
226 | |
227 | .ev_type = EV_ABS, |
228 | .ev_code_x = ABS_X, /* EV_REL */ |
229 | .ev_code_y = ABS_Y, /* EV_REL */ |
230 | .ev_code_z = ABS_Z, /* EV_REL */ |
231 | |
232 | .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY {x,y,z} */ |
233 | .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK, |
234 | .fifo_mode = ADXL_FIFO_STREAM, |
235 | .watermark = 0, |
236 | }; |
237 | |
238 | static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) |
239 | { |
240 | __le16 buf[3]; |
241 | |
242 | ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf); |
243 | |
244 | mutex_lock(&ac->mutex); |
245 | ac->saved.x = (s16) le16_to_cpu(buf[0]); |
246 | axis->x = ac->saved.x; |
247 | |
248 | ac->saved.y = (s16) le16_to_cpu(buf[1]); |
249 | axis->y = ac->saved.y; |
250 | |
251 | ac->saved.z = (s16) le16_to_cpu(buf[2]); |
252 | axis->z = ac->saved.z; |
253 | mutex_unlock(lock: &ac->mutex); |
254 | } |
255 | |
256 | static void adxl34x_service_ev_fifo(struct adxl34x *ac) |
257 | { |
258 | struct adxl34x_platform_data *pdata = &ac->pdata; |
259 | struct axis_triple axis; |
260 | |
261 | adxl34x_get_triple(ac, axis: &axis); |
262 | |
263 | input_event(dev: ac->input, type: pdata->ev_type, code: pdata->ev_code_x, |
264 | value: axis.x - ac->swcal.x); |
265 | input_event(dev: ac->input, type: pdata->ev_type, code: pdata->ev_code_y, |
266 | value: axis.y - ac->swcal.y); |
267 | input_event(dev: ac->input, type: pdata->ev_type, code: pdata->ev_code_z, |
268 | value: axis.z - ac->swcal.z); |
269 | } |
270 | |
271 | static void adxl34x_report_key_single(struct input_dev *input, int key) |
272 | { |
273 | input_report_key(dev: input, code: key, value: true); |
274 | input_sync(dev: input); |
275 | input_report_key(dev: input, code: key, value: false); |
276 | } |
277 | |
278 | static void adxl34x_send_key_events(struct adxl34x *ac, |
279 | struct adxl34x_platform_data *pdata, int status, int press) |
280 | { |
281 | int i; |
282 | |
283 | for (i = ADXL_X_AXIS; i <= ADXL_Z_AXIS; i++) { |
284 | if (status & (1 << (ADXL_Z_AXIS - i))) |
285 | input_report_key(dev: ac->input, |
286 | code: pdata->ev_code_tap[i], value: press); |
287 | } |
288 | } |
289 | |
290 | static void adxl34x_do_tap(struct adxl34x *ac, |
291 | struct adxl34x_platform_data *pdata, int status) |
292 | { |
293 | adxl34x_send_key_events(ac, pdata, status, press: true); |
294 | input_sync(dev: ac->input); |
295 | adxl34x_send_key_events(ac, pdata, status, press: false); |
296 | } |
297 | |
298 | static irqreturn_t adxl34x_irq(int irq, void *handle) |
299 | { |
300 | struct adxl34x *ac = handle; |
301 | struct adxl34x_platform_data *pdata = &ac->pdata; |
302 | int int_stat, tap_stat, samples, orient, orient_code; |
303 | |
304 | /* |
305 | * ACT_TAP_STATUS should be read before clearing the interrupt |
306 | * Avoid reading ACT_TAP_STATUS in case TAP detection is disabled |
307 | */ |
308 | |
309 | if (pdata->tap_axis_control & (TAP_X_EN | TAP_Y_EN | TAP_Z_EN)) |
310 | tap_stat = AC_READ(ac, ACT_TAP_STATUS); |
311 | else |
312 | tap_stat = 0; |
313 | |
314 | int_stat = AC_READ(ac, INT_SOURCE); |
315 | |
316 | if (int_stat & FREE_FALL) |
317 | adxl34x_report_key_single(input: ac->input, key: pdata->ev_code_ff); |
318 | |
319 | if (int_stat & OVERRUN) |
320 | dev_dbg(ac->dev, "OVERRUN\n" ); |
321 | |
322 | if (int_stat & (SINGLE_TAP | DOUBLE_TAP)) { |
323 | adxl34x_do_tap(ac, pdata, status: tap_stat); |
324 | |
325 | if (int_stat & DOUBLE_TAP) |
326 | adxl34x_do_tap(ac, pdata, status: tap_stat); |
327 | } |
328 | |
329 | if (pdata->ev_code_act_inactivity) { |
330 | if (int_stat & ACTIVITY) |
331 | input_report_key(dev: ac->input, |
332 | code: pdata->ev_code_act_inactivity, value: 1); |
333 | if (int_stat & INACTIVITY) |
334 | input_report_key(dev: ac->input, |
335 | code: pdata->ev_code_act_inactivity, value: 0); |
336 | } |
337 | |
338 | /* |
339 | * ORIENTATION SENSING ADXL346 only |
340 | */ |
341 | if (pdata->orientation_enable) { |
342 | orient = AC_READ(ac, ORIENT); |
343 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) && |
344 | (orient & ADXL346_2D_VALID)) { |
345 | |
346 | orient_code = ADXL346_2D_ORIENT(orient); |
347 | /* Report orientation only when it changes */ |
348 | if (ac->orient2d_saved != orient_code) { |
349 | ac->orient2d_saved = orient_code; |
350 | adxl34x_report_key_single(input: ac->input, |
351 | key: pdata->ev_codes_orient_2d[orient_code]); |
352 | } |
353 | } |
354 | |
355 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) && |
356 | (orient & ADXL346_3D_VALID)) { |
357 | |
358 | orient_code = ADXL346_3D_ORIENT(orient) - 1; |
359 | /* Report orientation only when it changes */ |
360 | if (ac->orient3d_saved != orient_code) { |
361 | ac->orient3d_saved = orient_code; |
362 | adxl34x_report_key_single(input: ac->input, |
363 | key: pdata->ev_codes_orient_3d[orient_code]); |
364 | } |
365 | } |
366 | } |
367 | |
368 | if (int_stat & (DATA_READY | WATERMARK)) { |
369 | |
370 | if (pdata->fifo_mode) |
371 | samples = ENTRIES(AC_READ(ac, FIFO_STATUS)) + 1; |
372 | else |
373 | samples = 1; |
374 | |
375 | for (; samples > 0; samples--) { |
376 | adxl34x_service_ev_fifo(ac); |
377 | /* |
378 | * To ensure that the FIFO has |
379 | * completely popped, there must be at least 5 us between |
380 | * the end of reading the data registers, signified by the |
381 | * transition to register 0x38 from 0x37 or the CS pin |
382 | * going high, and the start of new reads of the FIFO or |
383 | * reading the FIFO_STATUS register. For SPI operation at |
384 | * 1.5 MHz or lower, the register addressing portion of the |
385 | * transmission is sufficient delay to ensure the FIFO has |
386 | * completely popped. It is necessary for SPI operation |
387 | * greater than 1.5 MHz to de-assert the CS pin to ensure a |
388 | * total of 5 us, which is at most 3.4 us at 5 MHz |
389 | * operation. |
390 | */ |
391 | if (ac->fifo_delay && (samples > 1)) |
392 | udelay(3); |
393 | } |
394 | } |
395 | |
396 | input_sync(dev: ac->input); |
397 | |
398 | return IRQ_HANDLED; |
399 | } |
400 | |
401 | static void __adxl34x_disable(struct adxl34x *ac) |
402 | { |
403 | /* |
404 | * A '0' places the ADXL34x into standby mode |
405 | * with minimum power consumption. |
406 | */ |
407 | AC_WRITE(ac, POWER_CTL, 0); |
408 | } |
409 | |
410 | static void __adxl34x_enable(struct adxl34x *ac) |
411 | { |
412 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); |
413 | } |
414 | |
415 | static int adxl34x_suspend(struct device *dev) |
416 | { |
417 | struct adxl34x *ac = dev_get_drvdata(dev); |
418 | |
419 | mutex_lock(&ac->mutex); |
420 | |
421 | if (!ac->suspended && !ac->disabled && ac->opened) |
422 | __adxl34x_disable(ac); |
423 | |
424 | ac->suspended = true; |
425 | |
426 | mutex_unlock(lock: &ac->mutex); |
427 | |
428 | return 0; |
429 | } |
430 | |
431 | static int adxl34x_resume(struct device *dev) |
432 | { |
433 | struct adxl34x *ac = dev_get_drvdata(dev); |
434 | |
435 | mutex_lock(&ac->mutex); |
436 | |
437 | if (ac->suspended && !ac->disabled && ac->opened) |
438 | __adxl34x_enable(ac); |
439 | |
440 | ac->suspended = false; |
441 | |
442 | mutex_unlock(lock: &ac->mutex); |
443 | |
444 | return 0; |
445 | } |
446 | |
447 | static ssize_t adxl34x_disable_show(struct device *dev, |
448 | struct device_attribute *attr, char *buf) |
449 | { |
450 | struct adxl34x *ac = dev_get_drvdata(dev); |
451 | |
452 | return sprintf(buf, fmt: "%u\n" , ac->disabled); |
453 | } |
454 | |
455 | static ssize_t adxl34x_disable_store(struct device *dev, |
456 | struct device_attribute *attr, |
457 | const char *buf, size_t count) |
458 | { |
459 | struct adxl34x *ac = dev_get_drvdata(dev); |
460 | unsigned int val; |
461 | int error; |
462 | |
463 | error = kstrtouint(s: buf, base: 10, res: &val); |
464 | if (error) |
465 | return error; |
466 | |
467 | mutex_lock(&ac->mutex); |
468 | |
469 | if (!ac->suspended && ac->opened) { |
470 | if (val) { |
471 | if (!ac->disabled) |
472 | __adxl34x_disable(ac); |
473 | } else { |
474 | if (ac->disabled) |
475 | __adxl34x_enable(ac); |
476 | } |
477 | } |
478 | |
479 | ac->disabled = !!val; |
480 | |
481 | mutex_unlock(lock: &ac->mutex); |
482 | |
483 | return count; |
484 | } |
485 | |
486 | static DEVICE_ATTR(disable, 0664, adxl34x_disable_show, adxl34x_disable_store); |
487 | |
488 | static ssize_t adxl34x_calibrate_show(struct device *dev, |
489 | struct device_attribute *attr, char *buf) |
490 | { |
491 | struct adxl34x *ac = dev_get_drvdata(dev); |
492 | ssize_t count; |
493 | |
494 | mutex_lock(&ac->mutex); |
495 | count = sprintf(buf, fmt: "%d,%d,%d\n" , |
496 | ac->hwcal.x * 4 + ac->swcal.x, |
497 | ac->hwcal.y * 4 + ac->swcal.y, |
498 | ac->hwcal.z * 4 + ac->swcal.z); |
499 | mutex_unlock(lock: &ac->mutex); |
500 | |
501 | return count; |
502 | } |
503 | |
504 | static ssize_t adxl34x_calibrate_store(struct device *dev, |
505 | struct device_attribute *attr, |
506 | const char *buf, size_t count) |
507 | { |
508 | struct adxl34x *ac = dev_get_drvdata(dev); |
509 | |
510 | /* |
511 | * Hardware offset calibration has a resolution of 15.6 mg/LSB. |
512 | * We use HW calibration and handle the remaining bits in SW. (4mg/LSB) |
513 | */ |
514 | |
515 | mutex_lock(&ac->mutex); |
516 | ac->hwcal.x -= (ac->saved.x / 4); |
517 | ac->swcal.x = ac->saved.x % 4; |
518 | |
519 | ac->hwcal.y -= (ac->saved.y / 4); |
520 | ac->swcal.y = ac->saved.y % 4; |
521 | |
522 | ac->hwcal.z -= (ac->saved.z / 4); |
523 | ac->swcal.z = ac->saved.z % 4; |
524 | |
525 | AC_WRITE(ac, OFSX, (s8) ac->hwcal.x); |
526 | AC_WRITE(ac, OFSY, (s8) ac->hwcal.y); |
527 | AC_WRITE(ac, OFSZ, (s8) ac->hwcal.z); |
528 | mutex_unlock(lock: &ac->mutex); |
529 | |
530 | return count; |
531 | } |
532 | |
533 | static DEVICE_ATTR(calibrate, 0664, |
534 | adxl34x_calibrate_show, adxl34x_calibrate_store); |
535 | |
536 | static ssize_t adxl34x_rate_show(struct device *dev, |
537 | struct device_attribute *attr, char *buf) |
538 | { |
539 | struct adxl34x *ac = dev_get_drvdata(dev); |
540 | |
541 | return sprintf(buf, fmt: "%u\n" , RATE(ac->pdata.data_rate)); |
542 | } |
543 | |
544 | static ssize_t adxl34x_rate_store(struct device *dev, |
545 | struct device_attribute *attr, |
546 | const char *buf, size_t count) |
547 | { |
548 | struct adxl34x *ac = dev_get_drvdata(dev); |
549 | unsigned char val; |
550 | int error; |
551 | |
552 | error = kstrtou8(s: buf, base: 10, res: &val); |
553 | if (error) |
554 | return error; |
555 | |
556 | mutex_lock(&ac->mutex); |
557 | |
558 | ac->pdata.data_rate = RATE(val); |
559 | AC_WRITE(ac, BW_RATE, |
560 | ac->pdata.data_rate | |
561 | (ac->pdata.low_power_mode ? LOW_POWER : 0)); |
562 | |
563 | mutex_unlock(lock: &ac->mutex); |
564 | |
565 | return count; |
566 | } |
567 | |
568 | static DEVICE_ATTR(rate, 0664, adxl34x_rate_show, adxl34x_rate_store); |
569 | |
570 | static ssize_t adxl34x_autosleep_show(struct device *dev, |
571 | struct device_attribute *attr, char *buf) |
572 | { |
573 | struct adxl34x *ac = dev_get_drvdata(dev); |
574 | |
575 | return sprintf(buf, fmt: "%u\n" , |
576 | ac->pdata.power_mode & (PCTL_AUTO_SLEEP | PCTL_LINK) ? 1 : 0); |
577 | } |
578 | |
579 | static ssize_t adxl34x_autosleep_store(struct device *dev, |
580 | struct device_attribute *attr, |
581 | const char *buf, size_t count) |
582 | { |
583 | struct adxl34x *ac = dev_get_drvdata(dev); |
584 | unsigned int val; |
585 | int error; |
586 | |
587 | error = kstrtouint(s: buf, base: 10, res: &val); |
588 | if (error) |
589 | return error; |
590 | |
591 | mutex_lock(&ac->mutex); |
592 | |
593 | if (val) |
594 | ac->pdata.power_mode |= (PCTL_AUTO_SLEEP | PCTL_LINK); |
595 | else |
596 | ac->pdata.power_mode &= ~(PCTL_AUTO_SLEEP | PCTL_LINK); |
597 | |
598 | if (!ac->disabled && !ac->suspended && ac->opened) |
599 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); |
600 | |
601 | mutex_unlock(lock: &ac->mutex); |
602 | |
603 | return count; |
604 | } |
605 | |
606 | static DEVICE_ATTR(autosleep, 0664, |
607 | adxl34x_autosleep_show, adxl34x_autosleep_store); |
608 | |
609 | static ssize_t adxl34x_position_show(struct device *dev, |
610 | struct device_attribute *attr, char *buf) |
611 | { |
612 | struct adxl34x *ac = dev_get_drvdata(dev); |
613 | ssize_t count; |
614 | |
615 | mutex_lock(&ac->mutex); |
616 | count = sprintf(buf, fmt: "(%d, %d, %d)\n" , |
617 | ac->saved.x, ac->saved.y, ac->saved.z); |
618 | mutex_unlock(lock: &ac->mutex); |
619 | |
620 | return count; |
621 | } |
622 | |
623 | static DEVICE_ATTR(position, S_IRUGO, adxl34x_position_show, NULL); |
624 | |
625 | #ifdef ADXL_DEBUG |
626 | static ssize_t adxl34x_write_store(struct device *dev, |
627 | struct device_attribute *attr, |
628 | const char *buf, size_t count) |
629 | { |
630 | struct adxl34x *ac = dev_get_drvdata(dev); |
631 | unsigned int val; |
632 | int error; |
633 | |
634 | /* |
635 | * This allows basic ADXL register write access for debug purposes. |
636 | */ |
637 | error = kstrtouint(buf, 16, &val); |
638 | if (error) |
639 | return error; |
640 | |
641 | mutex_lock(&ac->mutex); |
642 | AC_WRITE(ac, val >> 8, val & 0xFF); |
643 | mutex_unlock(&ac->mutex); |
644 | |
645 | return count; |
646 | } |
647 | |
648 | static DEVICE_ATTR(write, 0664, NULL, adxl34x_write_store); |
649 | #endif |
650 | |
651 | static struct attribute *adxl34x_attributes[] = { |
652 | &dev_attr_disable.attr, |
653 | &dev_attr_calibrate.attr, |
654 | &dev_attr_rate.attr, |
655 | &dev_attr_autosleep.attr, |
656 | &dev_attr_position.attr, |
657 | #ifdef ADXL_DEBUG |
658 | &dev_attr_write.attr, |
659 | #endif |
660 | NULL |
661 | }; |
662 | |
663 | static const struct attribute_group adxl34x_attr_group = { |
664 | .attrs = adxl34x_attributes, |
665 | }; |
666 | |
667 | static int adxl34x_input_open(struct input_dev *input) |
668 | { |
669 | struct adxl34x *ac = input_get_drvdata(dev: input); |
670 | |
671 | mutex_lock(&ac->mutex); |
672 | |
673 | if (!ac->suspended && !ac->disabled) |
674 | __adxl34x_enable(ac); |
675 | |
676 | ac->opened = true; |
677 | |
678 | mutex_unlock(lock: &ac->mutex); |
679 | |
680 | return 0; |
681 | } |
682 | |
683 | static void adxl34x_input_close(struct input_dev *input) |
684 | { |
685 | struct adxl34x *ac = input_get_drvdata(dev: input); |
686 | |
687 | mutex_lock(&ac->mutex); |
688 | |
689 | if (!ac->suspended && !ac->disabled) |
690 | __adxl34x_disable(ac); |
691 | |
692 | ac->opened = false; |
693 | |
694 | mutex_unlock(lock: &ac->mutex); |
695 | } |
696 | |
697 | struct adxl34x *adxl34x_probe(struct device *dev, int irq, |
698 | bool fifo_delay_default, |
699 | const struct adxl34x_bus_ops *bops) |
700 | { |
701 | struct adxl34x *ac; |
702 | struct input_dev *input_dev; |
703 | const struct adxl34x_platform_data *pdata; |
704 | int err, range, i; |
705 | int revid; |
706 | |
707 | if (!irq) { |
708 | dev_err(dev, "no IRQ?\n" ); |
709 | err = -ENODEV; |
710 | goto err_out; |
711 | } |
712 | |
713 | ac = kzalloc(size: sizeof(*ac), GFP_KERNEL); |
714 | input_dev = input_allocate_device(); |
715 | if (!ac || !input_dev) { |
716 | err = -ENOMEM; |
717 | goto err_free_mem; |
718 | } |
719 | |
720 | ac->fifo_delay = fifo_delay_default; |
721 | |
722 | pdata = dev_get_platdata(dev); |
723 | if (!pdata) { |
724 | dev_dbg(dev, |
725 | "No platform data: Using default initialization\n" ); |
726 | pdata = &adxl34x_default_init; |
727 | } |
728 | |
729 | ac->pdata = *pdata; |
730 | pdata = &ac->pdata; |
731 | |
732 | ac->input = input_dev; |
733 | ac->dev = dev; |
734 | ac->irq = irq; |
735 | ac->bops = bops; |
736 | |
737 | mutex_init(&ac->mutex); |
738 | |
739 | input_dev->name = "ADXL34x accelerometer" ; |
740 | revid = AC_READ(ac, DEVID); |
741 | |
742 | switch (revid) { |
743 | case ID_ADXL345: |
744 | ac->model = 345; |
745 | break; |
746 | case ID_ADXL346: |
747 | ac->model = 346; |
748 | break; |
749 | default: |
750 | dev_err(dev, "Failed to probe %s\n" , input_dev->name); |
751 | err = -ENODEV; |
752 | goto err_free_mem; |
753 | } |
754 | |
755 | snprintf(buf: ac->phys, size: sizeof(ac->phys), fmt: "%s/input0" , dev_name(dev)); |
756 | |
757 | input_dev->phys = ac->phys; |
758 | input_dev->dev.parent = dev; |
759 | input_dev->id.product = ac->model; |
760 | input_dev->id.bustype = bops->bustype; |
761 | input_dev->open = adxl34x_input_open; |
762 | input_dev->close = adxl34x_input_close; |
763 | |
764 | input_set_drvdata(dev: input_dev, data: ac); |
765 | |
766 | __set_bit(ac->pdata.ev_type, input_dev->evbit); |
767 | |
768 | if (ac->pdata.ev_type == EV_REL) { |
769 | __set_bit(REL_X, input_dev->relbit); |
770 | __set_bit(REL_Y, input_dev->relbit); |
771 | __set_bit(REL_Z, input_dev->relbit); |
772 | } else { |
773 | /* EV_ABS */ |
774 | __set_bit(ABS_X, input_dev->absbit); |
775 | __set_bit(ABS_Y, input_dev->absbit); |
776 | __set_bit(ABS_Z, input_dev->absbit); |
777 | |
778 | if (pdata->data_range & FULL_RES) |
779 | range = ADXL_FULLRES_MAX_VAL; /* Signed 13-bit */ |
780 | else |
781 | range = ADXL_FIXEDRES_MAX_VAL; /* Signed 10-bit */ |
782 | |
783 | input_set_abs_params(dev: input_dev, ABS_X, min: -range, max: range, fuzz: 3, flat: 3); |
784 | input_set_abs_params(dev: input_dev, ABS_Y, min: -range, max: range, fuzz: 3, flat: 3); |
785 | input_set_abs_params(dev: input_dev, ABS_Z, min: -range, max: range, fuzz: 3, flat: 3); |
786 | } |
787 | |
788 | __set_bit(EV_KEY, input_dev->evbit); |
789 | __set_bit(pdata->ev_code_tap[ADXL_X_AXIS], input_dev->keybit); |
790 | __set_bit(pdata->ev_code_tap[ADXL_Y_AXIS], input_dev->keybit); |
791 | __set_bit(pdata->ev_code_tap[ADXL_Z_AXIS], input_dev->keybit); |
792 | |
793 | if (pdata->ev_code_ff) { |
794 | ac->int_mask = FREE_FALL; |
795 | __set_bit(pdata->ev_code_ff, input_dev->keybit); |
796 | } |
797 | |
798 | if (pdata->ev_code_act_inactivity) |
799 | __set_bit(pdata->ev_code_act_inactivity, input_dev->keybit); |
800 | |
801 | ac->int_mask |= ACTIVITY | INACTIVITY; |
802 | |
803 | if (pdata->watermark) { |
804 | ac->int_mask |= WATERMARK; |
805 | if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) |
806 | ac->pdata.fifo_mode |= FIFO_STREAM; |
807 | } else { |
808 | ac->int_mask |= DATA_READY; |
809 | } |
810 | |
811 | if (pdata->tap_axis_control & (TAP_X_EN | TAP_Y_EN | TAP_Z_EN)) |
812 | ac->int_mask |= SINGLE_TAP | DOUBLE_TAP; |
813 | |
814 | if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) |
815 | ac->fifo_delay = false; |
816 | |
817 | AC_WRITE(ac, POWER_CTL, 0); |
818 | |
819 | err = request_threaded_irq(irq: ac->irq, NULL, thread_fn: adxl34x_irq, |
820 | IRQF_ONESHOT, name: dev_name(dev), dev: ac); |
821 | if (err) { |
822 | dev_err(dev, "irq %d busy?\n" , ac->irq); |
823 | goto err_free_mem; |
824 | } |
825 | |
826 | err = sysfs_create_group(kobj: &dev->kobj, grp: &adxl34x_attr_group); |
827 | if (err) |
828 | goto err_free_irq; |
829 | |
830 | err = input_register_device(input_dev); |
831 | if (err) |
832 | goto err_remove_attr; |
833 | |
834 | AC_WRITE(ac, OFSX, pdata->x_axis_offset); |
835 | ac->hwcal.x = pdata->x_axis_offset; |
836 | AC_WRITE(ac, OFSY, pdata->y_axis_offset); |
837 | ac->hwcal.y = pdata->y_axis_offset; |
838 | AC_WRITE(ac, OFSZ, pdata->z_axis_offset); |
839 | ac->hwcal.z = pdata->z_axis_offset; |
840 | AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold); |
841 | AC_WRITE(ac, DUR, pdata->tap_duration); |
842 | AC_WRITE(ac, LATENT, pdata->tap_latency); |
843 | AC_WRITE(ac, WINDOW, pdata->tap_window); |
844 | AC_WRITE(ac, THRESH_ACT, pdata->activity_threshold); |
845 | AC_WRITE(ac, THRESH_INACT, pdata->inactivity_threshold); |
846 | AC_WRITE(ac, TIME_INACT, pdata->inactivity_time); |
847 | AC_WRITE(ac, THRESH_FF, pdata->free_fall_threshold); |
848 | AC_WRITE(ac, TIME_FF, pdata->free_fall_time); |
849 | AC_WRITE(ac, TAP_AXES, pdata->tap_axis_control); |
850 | AC_WRITE(ac, ACT_INACT_CTL, pdata->act_axis_control); |
851 | AC_WRITE(ac, BW_RATE, RATE(ac->pdata.data_rate) | |
852 | (pdata->low_power_mode ? LOW_POWER : 0)); |
853 | AC_WRITE(ac, DATA_FORMAT, pdata->data_range); |
854 | AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) | |
855 | SAMPLES(pdata->watermark)); |
856 | |
857 | if (pdata->use_int2) { |
858 | /* Map all INTs to INT2 */ |
859 | AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN); |
860 | } else { |
861 | /* Map all INTs to INT1 */ |
862 | AC_WRITE(ac, INT_MAP, 0); |
863 | } |
864 | |
865 | if (ac->model == 346 && ac->pdata.orientation_enable) { |
866 | AC_WRITE(ac, ORIENT_CONF, |
867 | ORIENT_DEADZONE(ac->pdata.deadzone_angle) | |
868 | ORIENT_DIVISOR(ac->pdata.divisor_length)); |
869 | |
870 | ac->orient2d_saved = 1234; |
871 | ac->orient3d_saved = 1234; |
872 | |
873 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) |
874 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) |
875 | __set_bit(pdata->ev_codes_orient_3d[i], |
876 | input_dev->keybit); |
877 | |
878 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) |
879 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) |
880 | __set_bit(pdata->ev_codes_orient_2d[i], |
881 | input_dev->keybit); |
882 | } else { |
883 | ac->pdata.orientation_enable = 0; |
884 | } |
885 | |
886 | AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN); |
887 | |
888 | ac->pdata.power_mode &= (PCTL_AUTO_SLEEP | PCTL_LINK); |
889 | |
890 | return ac; |
891 | |
892 | err_remove_attr: |
893 | sysfs_remove_group(kobj: &dev->kobj, grp: &adxl34x_attr_group); |
894 | err_free_irq: |
895 | free_irq(ac->irq, ac); |
896 | err_free_mem: |
897 | input_free_device(dev: input_dev); |
898 | kfree(objp: ac); |
899 | err_out: |
900 | return ERR_PTR(error: err); |
901 | } |
902 | EXPORT_SYMBOL_GPL(adxl34x_probe); |
903 | |
904 | void adxl34x_remove(struct adxl34x *ac) |
905 | { |
906 | sysfs_remove_group(kobj: &ac->dev->kobj, grp: &adxl34x_attr_group); |
907 | free_irq(ac->irq, ac); |
908 | input_unregister_device(ac->input); |
909 | dev_dbg(ac->dev, "unregistered accelerometer\n" ); |
910 | kfree(objp: ac); |
911 | } |
912 | EXPORT_SYMBOL_GPL(adxl34x_remove); |
913 | |
914 | EXPORT_GPL_SIMPLE_DEV_PM_OPS(adxl34x_pm, adxl34x_suspend, adxl34x_resume); |
915 | |
916 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>" ); |
917 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer Driver" ); |
918 | MODULE_LICENSE("GPL" ); |
919 | |