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