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