Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add CMA3000 accelerometer driver

Add support for CMA3000 Tri-axis accelerometer, which supports Motion
detect, Measurement and Free fall modes. CMA3000 supports both I2C/SPI
bus for communication, currently the driver supports I2C based
communication.

Signed-off-by: Hemanth V <hemanthv@ti.com>
Reviewed-by: Jonathan Cameron <jic23@cam.ac.uk>
Reviewed-by: Sergio Aguirre <saaguirre@ti.com>
Reviewed-by: Shubhrajyoti <Shubhrajyoti@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Hemanth V and committed by
Dmitry Torokhov
b029ffaf 33e808c3

+781
+115
Documentation/input/cma3000_d0x.txt
··· 1 + Kernel driver for CMA3000-D0x 2 + ============================ 3 + 4 + Supported chips: 5 + * VTI CMA3000-D0x 6 + Datasheet: 7 + CMA3000-D0X Product Family Specification 8281000A.02.pdf 8 + <http://www.vti.fi/en/> 9 + 10 + Author: Hemanth V <hemanthv@ti.com> 11 + 12 + 13 + Description 14 + ----------- 15 + CMA3000 Tri-axis accelerometer supports Motion detect, Measurement and 16 + Free fall modes. 17 + 18 + Motion Detect Mode: Its the low power mode where interrupts are generated only 19 + when motion exceeds the defined thresholds. 20 + 21 + Measurement Mode: This mode is used to read the acceleration data on X,Y,Z 22 + axis and supports 400, 100, 40 Hz sample frequency. 23 + 24 + Free fall Mode: This mode is intended to save system resources. 25 + 26 + Threshold values: Chip supports defining threshold values for above modes 27 + which includes time and g value. Refer product specifications for more details. 28 + 29 + CMA3000 chip supports mutually exclusive I2C and SPI interfaces for 30 + communication, currently the driver supports I2C based communication only. 31 + Initial configuration for bus mode is set in non volatile memory and can later 32 + be modified through bus interface command. 33 + 34 + Driver reports acceleration data through input subsystem. It generates ABS_MISC 35 + event with value 1 when free fall is detected. 36 + 37 + Platform data need to be configured for initial default values. 38 + 39 + Platform Data 40 + ------------- 41 + fuzz_x: Noise on X Axis 42 + 43 + fuzz_y: Noise on Y Axis 44 + 45 + fuzz_z: Noise on Z Axis 46 + 47 + g_range: G range in milli g i.e 2000 or 8000 48 + 49 + mode: Default Operating mode 50 + 51 + mdthr: Motion detect g range threshold value 52 + 53 + mdfftmr: Motion detect and free fall time threshold value 54 + 55 + ffthr: Free fall g range threshold value 56 + 57 + Input Interface 58 + -------------- 59 + Input driver version is 1.0.0 60 + Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0 61 + Input device name: "cma3000-accelerometer" 62 + Supported events: 63 + Event type 0 (Sync) 64 + Event type 3 (Absolute) 65 + Event code 0 (X) 66 + Value 47 67 + Min -8000 68 + Max 8000 69 + Fuzz 200 70 + Event code 1 (Y) 71 + Value -28 72 + Min -8000 73 + Max 8000 74 + Fuzz 200 75 + Event code 2 (Z) 76 + Value 905 77 + Min -8000 78 + Max 8000 79 + Fuzz 200 80 + Event code 40 (Misc) 81 + Value 0 82 + Min 0 83 + Max 1 84 + Event type 4 (Misc) 85 + 86 + 87 + Register/Platform parameters Description 88 + ---------------------------------------- 89 + 90 + mode: 91 + 0: power down mode 92 + 1: 100 Hz Measurement mode 93 + 2: 400 Hz Measurement mode 94 + 3: 40 Hz Measurement mode 95 + 4: Motion Detect mode (default) 96 + 5: 100 Hz Free fall mode 97 + 6: 40 Hz Free fall mode 98 + 7: Power off mode 99 + 100 + grange: 101 + 2000: 2000 mg or 2G Range 102 + 8000: 8000 mg or 8G Range 103 + 104 + mdthr: 105 + X: X * 71mg (8G Range) 106 + X: X * 18mg (2G Range) 107 + 108 + mdfftmr: 109 + X: (X & 0x70) * 100 ms (MDTMR) 110 + (X & 0x0F) * 2.5 ms (FFTMR 400 Hz) 111 + (X & 0x0F) * 10 ms (FFTMR 100 Hz) 112 + 113 + ffthr: 114 + X: (X >> 2) * 18mg (2G Range) 115 + X: (X & 0x0F) * 71 mg (8G Range)
+24
drivers/input/misc/Kconfig
··· 448 448 To compile this driver as a module, choose M here: the 449 449 module will be called adxl34x-spi. 450 450 451 + config INPUT_CMA3000 452 + tristate "VTI CMA3000 Tri-axis accelerometer" 453 + help 454 + Say Y here if you want to use VTI CMA3000_D0x Accelerometer 455 + driver 456 + 457 + This driver currently only supports I2C interface to the 458 + controller. Also select the I2C method. 459 + 460 + If unsure, say N 461 + 462 + To compile this driver as a module, choose M here: the 463 + module will be called cma3000_d0x. 464 + 465 + config INPUT_CMA3000_I2C 466 + tristate "Support I2C bus connection" 467 + depends on INPUT_CMA3000 && I2C 468 + help 469 + Say Y here if you want to use VTI CMA3000_D0x Accelerometer 470 + through I2C interface. 471 + 472 + To compile this driver as a module, choose M here: the 473 + module will be called cma3000_d0x_i2c. 474 + 451 475 endif
+2
drivers/input/misc/Makefile
··· 18 18 obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o 19 19 obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o 20 20 obj-$(CONFIG_INPUT_CM109) += cm109.o 21 + obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o 22 + obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o 21 23 obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o 22 24 obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o 23 25 obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
+398
drivers/input/misc/cma3000_d0x.c
··· 1 + /* 2 + * VTI CMA3000_D0x Accelerometer driver 3 + * 4 + * Copyright (C) 2010 Texas Instruments 5 + * Author: Hemanth V <hemanthv@ti.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include <linux/types.h> 21 + #include <linux/interrupt.h> 22 + #include <linux/delay.h> 23 + #include <linux/slab.h> 24 + #include <linux/input.h> 25 + #include <linux/input/cma3000.h> 26 + 27 + #include "cma3000_d0x.h" 28 + 29 + #define CMA3000_WHOAMI 0x00 30 + #define CMA3000_REVID 0x01 31 + #define CMA3000_CTRL 0x02 32 + #define CMA3000_STATUS 0x03 33 + #define CMA3000_RSTR 0x04 34 + #define CMA3000_INTSTATUS 0x05 35 + #define CMA3000_DOUTX 0x06 36 + #define CMA3000_DOUTY 0x07 37 + #define CMA3000_DOUTZ 0x08 38 + #define CMA3000_MDTHR 0x09 39 + #define CMA3000_MDFFTMR 0x0A 40 + #define CMA3000_FFTHR 0x0B 41 + 42 + #define CMA3000_RANGE2G (1 << 7) 43 + #define CMA3000_RANGE8G (0 << 7) 44 + #define CMA3000_BUSI2C (0 << 4) 45 + #define CMA3000_MODEMASK (7 << 1) 46 + #define CMA3000_GRANGEMASK (1 << 7) 47 + 48 + #define CMA3000_STATUS_PERR 1 49 + #define CMA3000_INTSTATUS_FFDET (1 << 2) 50 + 51 + /* Settling time delay in ms */ 52 + #define CMA3000_SETDELAY 30 53 + 54 + /* Delay for clearing interrupt in us */ 55 + #define CMA3000_INTDELAY 44 56 + 57 + 58 + /* 59 + * Bit weights in mg for bit 0, other bits need 60 + * multipy factor 2^n. Eight bit is the sign bit. 61 + */ 62 + #define BIT_TO_2G 18 63 + #define BIT_TO_8G 71 64 + 65 + struct cma3000_accl_data { 66 + const struct cma3000_bus_ops *bus_ops; 67 + const struct cma3000_platform_data *pdata; 68 + 69 + struct device *dev; 70 + struct input_dev *input_dev; 71 + 72 + int bit_to_mg; 73 + int irq; 74 + 75 + int g_range; 76 + u8 mode; 77 + 78 + struct mutex mutex; 79 + bool opened; 80 + bool suspended; 81 + }; 82 + 83 + #define CMA3000_READ(data, reg, msg) \ 84 + (data->bus_ops->read(data->dev, reg, msg)) 85 + #define CMA3000_SET(data, reg, val, msg) \ 86 + ((data)->bus_ops->write(data->dev, reg, val, msg)) 87 + 88 + /* 89 + * Conversion for each of the eight modes to g, depending 90 + * on G range i.e 2G or 8G. Some modes always operate in 91 + * 8G. 92 + */ 93 + 94 + static int mode_to_mg[8][2] = { 95 + { 0, 0 }, 96 + { BIT_TO_8G, BIT_TO_2G }, 97 + { BIT_TO_8G, BIT_TO_2G }, 98 + { BIT_TO_8G, BIT_TO_8G }, 99 + { BIT_TO_8G, BIT_TO_8G }, 100 + { BIT_TO_8G, BIT_TO_2G }, 101 + { BIT_TO_8G, BIT_TO_2G }, 102 + { 0, 0}, 103 + }; 104 + 105 + static void decode_mg(struct cma3000_accl_data *data, int *datax, 106 + int *datay, int *dataz) 107 + { 108 + /* Data in 2's complement, convert to mg */ 109 + *datax = ((s8)*datax) * data->bit_to_mg; 110 + *datay = ((s8)*datay) * data->bit_to_mg; 111 + *dataz = ((s8)*dataz) * data->bit_to_mg; 112 + } 113 + 114 + static irqreturn_t cma3000_thread_irq(int irq, void *dev_id) 115 + { 116 + struct cma3000_accl_data *data = dev_id; 117 + int datax, datay, dataz; 118 + u8 ctrl, mode, range, intr_status; 119 + 120 + intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status"); 121 + if (intr_status < 0) 122 + return IRQ_NONE; 123 + 124 + /* Check if free fall is detected, report immediately */ 125 + if (intr_status & CMA3000_INTSTATUS_FFDET) { 126 + input_report_abs(data->input_dev, ABS_MISC, 1); 127 + input_sync(data->input_dev); 128 + } else { 129 + input_report_abs(data->input_dev, ABS_MISC, 0); 130 + } 131 + 132 + datax = CMA3000_READ(data, CMA3000_DOUTX, "X"); 133 + datay = CMA3000_READ(data, CMA3000_DOUTY, "Y"); 134 + dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z"); 135 + 136 + ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl"); 137 + mode = (ctrl & CMA3000_MODEMASK) >> 1; 138 + range = (ctrl & CMA3000_GRANGEMASK) >> 7; 139 + 140 + data->bit_to_mg = mode_to_mg[mode][range]; 141 + 142 + /* Interrupt not for this device */ 143 + if (data->bit_to_mg == 0) 144 + return IRQ_NONE; 145 + 146 + /* Decode register values to milli g */ 147 + decode_mg(data, &datax, &datay, &dataz); 148 + 149 + input_report_abs(data->input_dev, ABS_X, datax); 150 + input_report_abs(data->input_dev, ABS_Y, datay); 151 + input_report_abs(data->input_dev, ABS_Z, dataz); 152 + input_sync(data->input_dev); 153 + 154 + return IRQ_HANDLED; 155 + } 156 + 157 + static int cma3000_reset(struct cma3000_accl_data *data) 158 + { 159 + int val; 160 + 161 + /* Reset sequence */ 162 + CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset"); 163 + CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset"); 164 + CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset"); 165 + 166 + /* Settling time delay */ 167 + mdelay(10); 168 + 169 + val = CMA3000_READ(data, CMA3000_STATUS, "Status"); 170 + if (val < 0) { 171 + dev_err(data->dev, "Reset failed\n"); 172 + return val; 173 + } 174 + 175 + if (val & CMA3000_STATUS_PERR) { 176 + dev_err(data->dev, "Parity Error\n"); 177 + return -EIO; 178 + } 179 + 180 + return 0; 181 + } 182 + 183 + static int cma3000_poweron(struct cma3000_accl_data *data) 184 + { 185 + const struct cma3000_platform_data *pdata = data->pdata; 186 + u8 ctrl = 0; 187 + int ret; 188 + 189 + if (data->g_range == CMARANGE_2G) { 190 + ctrl = (data->mode << 1) | CMA3000_RANGE2G; 191 + } else if (data->g_range == CMARANGE_8G) { 192 + ctrl = (data->mode << 1) | CMA3000_RANGE8G; 193 + } else { 194 + dev_info(data->dev, 195 + "Invalid G range specified, assuming 8G\n"); 196 + ctrl = (data->mode << 1) | CMA3000_RANGE8G; 197 + } 198 + 199 + ctrl |= data->bus_ops->ctrl_mod; 200 + 201 + CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr, 202 + "Motion Detect Threshold"); 203 + CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr, 204 + "Time register"); 205 + CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr, 206 + "Free fall threshold"); 207 + ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting"); 208 + if (ret < 0) 209 + return -EIO; 210 + 211 + msleep(CMA3000_SETDELAY); 212 + 213 + return 0; 214 + } 215 + 216 + static int cma3000_poweroff(struct cma3000_accl_data *data) 217 + { 218 + int ret; 219 + 220 + ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting"); 221 + msleep(CMA3000_SETDELAY); 222 + 223 + return ret; 224 + } 225 + 226 + static int cma3000_open(struct input_dev *input_dev) 227 + { 228 + struct cma3000_accl_data *data = input_get_drvdata(input_dev); 229 + 230 + mutex_lock(&data->mutex); 231 + 232 + if (!data->suspended) 233 + cma3000_poweron(data); 234 + 235 + data->opened = true; 236 + 237 + mutex_unlock(&data->mutex); 238 + 239 + return 0; 240 + } 241 + 242 + static void cma3000_close(struct input_dev *input_dev) 243 + { 244 + struct cma3000_accl_data *data = input_get_drvdata(input_dev); 245 + 246 + mutex_lock(&data->mutex); 247 + 248 + if (!data->suspended) 249 + cma3000_poweroff(data); 250 + 251 + data->opened = false; 252 + 253 + mutex_unlock(&data->mutex); 254 + } 255 + 256 + void cma3000_suspend(struct cma3000_accl_data *data) 257 + { 258 + mutex_lock(&data->mutex); 259 + 260 + if (!data->suspended && data->opened) 261 + cma3000_poweroff(data); 262 + 263 + data->suspended = true; 264 + 265 + mutex_unlock(&data->mutex); 266 + } 267 + EXPORT_SYMBOL(cma3000_suspend); 268 + 269 + 270 + void cma3000_resume(struct cma3000_accl_data *data) 271 + { 272 + mutex_lock(&data->mutex); 273 + 274 + if (data->suspended && data->opened) 275 + cma3000_poweron(data); 276 + 277 + data->suspended = false; 278 + 279 + mutex_unlock(&data->mutex); 280 + } 281 + EXPORT_SYMBOL(cma3000_resume); 282 + 283 + struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, 284 + const struct cma3000_bus_ops *bops) 285 + { 286 + const struct cma3000_platform_data *pdata = dev->platform_data; 287 + struct cma3000_accl_data *data; 288 + struct input_dev *input_dev; 289 + int rev; 290 + int error; 291 + 292 + if (!pdata) { 293 + dev_err(dev, "platform data not found\n"); 294 + error = -EINVAL; 295 + goto err_out; 296 + } 297 + 298 + 299 + /* if no IRQ return error */ 300 + if (irq == 0) { 301 + error = -EINVAL; 302 + goto err_out; 303 + } 304 + 305 + data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL); 306 + input_dev = input_allocate_device(); 307 + if (!data || !input_dev) { 308 + error = -ENOMEM; 309 + goto err_free_mem; 310 + } 311 + 312 + data->dev = dev; 313 + data->input_dev = input_dev; 314 + data->bus_ops = bops; 315 + data->pdata = pdata; 316 + data->irq = irq; 317 + mutex_init(&data->mutex); 318 + 319 + data->mode = pdata->mode; 320 + if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) { 321 + data->mode = CMAMODE_MOTDET; 322 + dev_warn(dev, 323 + "Invalid mode specified, assuming Motion Detect\n"); 324 + } 325 + 326 + data->g_range = pdata->g_range; 327 + if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) { 328 + dev_info(dev, 329 + "Invalid G range specified, assuming 8G\n"); 330 + data->g_range = CMARANGE_8G; 331 + } 332 + 333 + input_dev->name = "cma3000-accelerometer"; 334 + input_dev->id.bustype = bops->bustype; 335 + input_dev->open = cma3000_open; 336 + input_dev->close = cma3000_close; 337 + 338 + __set_bit(EV_ABS, input_dev->evbit); 339 + 340 + input_set_abs_params(input_dev, ABS_X, 341 + -data->g_range, data->g_range, pdata->fuzz_x, 0); 342 + input_set_abs_params(input_dev, ABS_Y, 343 + -data->g_range, data->g_range, pdata->fuzz_y, 0); 344 + input_set_abs_params(input_dev, ABS_Z, 345 + -data->g_range, data->g_range, pdata->fuzz_z, 0); 346 + input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0); 347 + 348 + input_set_drvdata(input_dev, data); 349 + 350 + error = cma3000_reset(data); 351 + if (error) 352 + goto err_free_mem; 353 + 354 + rev = CMA3000_READ(data, CMA3000_REVID, "Revid"); 355 + if (rev < 0) { 356 + error = rev; 357 + goto err_free_mem; 358 + } 359 + 360 + pr_info("CMA3000 Accelerometer: Revision %x\n", rev); 361 + 362 + error = request_threaded_irq(irq, NULL, cma3000_thread_irq, 363 + pdata->irqflags | IRQF_ONESHOT, 364 + "cma3000_d0x", data); 365 + if (error) { 366 + dev_err(dev, "request_threaded_irq failed\n"); 367 + goto err_free_mem; 368 + } 369 + 370 + error = input_register_device(data->input_dev); 371 + if (error) { 372 + dev_err(dev, "Unable to register input device\n"); 373 + goto err_free_irq; 374 + } 375 + 376 + return data; 377 + 378 + err_free_irq: 379 + free_irq(irq, data); 380 + err_free_mem: 381 + input_free_device(input_dev); 382 + kfree(data); 383 + err_out: 384 + return ERR_PTR(error); 385 + } 386 + EXPORT_SYMBOL(cma3000_init); 387 + 388 + void cma3000_exit(struct cma3000_accl_data *data) 389 + { 390 + free_irq(data->irq, data); 391 + input_unregister_device(data->input_dev); 392 + kfree(data); 393 + } 394 + EXPORT_SYMBOL(cma3000_exit); 395 + 396 + MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver"); 397 + MODULE_LICENSE("GPL"); 398 + MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
+42
drivers/input/misc/cma3000_d0x.h
··· 1 + /* 2 + * VTI CMA3000_D0x Accelerometer driver 3 + * 4 + * Copyright (C) 2010 Texas Instruments 5 + * Author: Hemanth V <hemanthv@ti.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef _INPUT_CMA3000_H 21 + #define _INPUT_CMA3000_H 22 + 23 + #include <linux/types.h> 24 + #include <linux/input.h> 25 + 26 + struct device; 27 + struct cma3000_accl_data; 28 + 29 + struct cma3000_bus_ops { 30 + u16 bustype; 31 + u8 ctrl_mod; 32 + int (*read)(struct device *, u8, char *); 33 + int (*write)(struct device *, u8, u8, char *); 34 + }; 35 + 36 + struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, 37 + const struct cma3000_bus_ops *bops); 38 + void cma3000_exit(struct cma3000_accl_data *); 39 + void cma3000_suspend(struct cma3000_accl_data *); 40 + void cma3000_resume(struct cma3000_accl_data *); 41 + 42 + #endif
+141
drivers/input/misc/cma3000_d0x_i2c.c
··· 1 + /* 2 + * Implements I2C interface for VTI CMA300_D0x Accelerometer driver 3 + * 4 + * Copyright (C) 2010 Texas Instruments 5 + * Author: Hemanth V <hemanthv@ti.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/i2c.h> 22 + #include <linux/input/cma3000.h> 23 + #include "cma3000_d0x.h" 24 + 25 + static int cma3000_i2c_set(struct device *dev, 26 + u8 reg, u8 val, char *msg) 27 + { 28 + struct i2c_client *client = to_i2c_client(dev); 29 + int ret; 30 + 31 + ret = i2c_smbus_write_byte_data(client, reg, val); 32 + if (ret < 0) 33 + dev_err(&client->dev, 34 + "%s failed (%s, %d)\n", __func__, msg, ret); 35 + return ret; 36 + } 37 + 38 + static int cma3000_i2c_read(struct device *dev, u8 reg, char *msg) 39 + { 40 + struct i2c_client *client = to_i2c_client(dev); 41 + int ret; 42 + 43 + ret = i2c_smbus_read_byte_data(client, reg); 44 + if (ret < 0) 45 + dev_err(&client->dev, 46 + "%s failed (%s, %d)\n", __func__, msg, ret); 47 + return ret; 48 + } 49 + 50 + static const struct cma3000_bus_ops cma3000_i2c_bops = { 51 + .bustype = BUS_I2C, 52 + #define CMA3000_BUSI2C (0 << 4) 53 + .ctrl_mod = CMA3000_BUSI2C, 54 + .read = cma3000_i2c_read, 55 + .write = cma3000_i2c_set, 56 + }; 57 + 58 + static int __devinit cma3000_i2c_probe(struct i2c_client *client, 59 + const struct i2c_device_id *id) 60 + { 61 + struct cma3000_accl_data *data; 62 + 63 + data = cma3000_init(&client->dev, client->irq, &cma3000_i2c_bops); 64 + if (IS_ERR(data)) 65 + return PTR_ERR(data); 66 + 67 + i2c_set_clientdata(client, data); 68 + 69 + return 0; 70 + } 71 + 72 + static int __devexit cma3000_i2c_remove(struct i2c_client *client) 73 + { 74 + struct cma3000_accl_data *data = i2c_get_clientdata(client); 75 + 76 + cma3000_exit(data); 77 + 78 + return 0; 79 + } 80 + 81 + #ifdef CONFIG_PM 82 + static int cma3000_i2c_suspend(struct device *dev) 83 + { 84 + struct i2c_client *client = to_i2c_client(dev); 85 + struct cma3000_accl_data *data = i2c_get_clientdata(client); 86 + 87 + cma3000_suspend(data); 88 + 89 + return 0; 90 + } 91 + 92 + static int cma3000_i2c_resume(struct device *dev) 93 + { 94 + struct i2c_client *client = to_i2c_client(dev); 95 + struct cma3000_accl_data *data = i2c_get_clientdata(client); 96 + 97 + cma3000_resume(data); 98 + 99 + return 0; 100 + } 101 + 102 + static const struct dev_pm_ops cma3000_i2c_pm_ops = { 103 + .suspend = cma3000_i2c_suspend, 104 + .resume = cma3000_i2c_resume, 105 + }; 106 + #endif 107 + 108 + static const struct i2c_device_id cma3000_i2c_id[] = { 109 + { "cma3000_d01", 0 }, 110 + { }, 111 + }; 112 + 113 + static struct i2c_driver cma3000_i2c_driver = { 114 + .probe = cma3000_i2c_probe, 115 + .remove = __devexit_p(cma3000_i2c_remove), 116 + .id_table = cma3000_i2c_id, 117 + .driver = { 118 + .name = "cma3000_i2c_accl", 119 + .owner = THIS_MODULE, 120 + #ifdef CONFIG_PM 121 + .pm = &cma3000_i2c_pm_ops, 122 + #endif 123 + }, 124 + }; 125 + 126 + static int __init cma3000_i2c_init(void) 127 + { 128 + return i2c_add_driver(&cma3000_i2c_driver); 129 + } 130 + 131 + static void __exit cma3000_i2c_exit(void) 132 + { 133 + i2c_del_driver(&cma3000_i2c_driver); 134 + } 135 + 136 + module_init(cma3000_i2c_init); 137 + module_exit(cma3000_i2c_exit); 138 + 139 + MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver"); 140 + MODULE_LICENSE("GPL"); 141 + MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
+59
include/linux/input/cma3000.h
··· 1 + /* 2 + * VTI CMA3000_Dxx Accelerometer driver 3 + * 4 + * Copyright (C) 2010 Texas Instruments 5 + * Author: Hemanth V <hemanthv@ti.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef _LINUX_CMA3000_H 21 + #define _LINUX_CMA3000_H 22 + 23 + #define CMAMODE_DEFAULT 0 24 + #define CMAMODE_MEAS100 1 25 + #define CMAMODE_MEAS400 2 26 + #define CMAMODE_MEAS40 3 27 + #define CMAMODE_MOTDET 4 28 + #define CMAMODE_FF100 5 29 + #define CMAMODE_FF400 6 30 + #define CMAMODE_POFF 7 31 + 32 + #define CMARANGE_2G 2000 33 + #define CMARANGE_8G 8000 34 + 35 + /** 36 + * struct cma3000_i2c_platform_data - CMA3000 Platform data 37 + * @fuzz_x: Noise on X Axis 38 + * @fuzz_y: Noise on Y Axis 39 + * @fuzz_z: Noise on Z Axis 40 + * @g_range: G range in milli g i.e 2000 or 8000 41 + * @mode: Operating mode 42 + * @mdthr: Motion detect threshold value 43 + * @mdfftmr: Motion detect and free fall time value 44 + * @ffthr: Free fall threshold value 45 + */ 46 + 47 + struct cma3000_platform_data { 48 + int fuzz_x; 49 + int fuzz_y; 50 + int fuzz_z; 51 + int g_range; 52 + uint8_t mode; 53 + uint8_t mdthr; 54 + uint8_t mdfftmr; 55 + uint8_t ffthr; 56 + unsigned long irqflags; 57 + }; 58 + 59 + #endif