1c17ca3f5SEric Andersson /* 2c17ca3f5SEric Andersson * Copyright (c) 2011 Bosch Sensortec GmbH 3c17ca3f5SEric Andersson * Copyright (c) 2011 Unixphere 4c17ca3f5SEric Andersson * 5c17ca3f5SEric Andersson * This driver adds support for Bosch Sensortec's digital acceleration 6c17ca3f5SEric Andersson * sensors BMA150 and SMB380. 7c17ca3f5SEric Andersson * The SMB380 is fully compatible with BMA150 and only differs in packaging. 8c17ca3f5SEric Andersson * 9c17ca3f5SEric Andersson * The datasheet for the BMA150 chip can be found here: 10c17ca3f5SEric Andersson * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf 11c17ca3f5SEric Andersson * 12c17ca3f5SEric Andersson * This program is free software; you can redistribute it and/or modify 13c17ca3f5SEric Andersson * it under the terms of the GNU General Public License as published by 14c17ca3f5SEric Andersson * the Free Software Foundation; either version 2 of the License, or 15c17ca3f5SEric Andersson * (at your option) any later version. 16c17ca3f5SEric Andersson * 17c17ca3f5SEric Andersson * This program is distributed in the hope that it will be useful, 18c17ca3f5SEric Andersson * but WITHOUT ANY WARRANTY; without even the implied warranty of 19c17ca3f5SEric Andersson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20c17ca3f5SEric Andersson * GNU General Public License for more details. 21c17ca3f5SEric Andersson * 22c17ca3f5SEric Andersson * You should have received a copy of the GNU General Public License 23c17ca3f5SEric Andersson * along with this program; if not, write to the Free Software 24c17ca3f5SEric Andersson * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25c17ca3f5SEric Andersson */ 26c17ca3f5SEric Andersson #include <linux/kernel.h> 27c17ca3f5SEric Andersson #include <linux/module.h> 28c17ca3f5SEric Andersson #include <linux/i2c.h> 29c17ca3f5SEric Andersson #include <linux/input.h> 30c17ca3f5SEric Andersson #include <linux/input-polldev.h> 31c17ca3f5SEric Andersson #include <linux/interrupt.h> 32c17ca3f5SEric Andersson #include <linux/delay.h> 33c17ca3f5SEric Andersson #include <linux/slab.h> 34c17ca3f5SEric Andersson #include <linux/pm.h> 35c17ca3f5SEric Andersson #include <linux/pm_runtime.h> 36c17ca3f5SEric Andersson #include <linux/bma150.h> 37c17ca3f5SEric Andersson 38c17ca3f5SEric Andersson #define ABSMAX_ACC_VAL 0x01FF 39c17ca3f5SEric Andersson #define ABSMIN_ACC_VAL -(ABSMAX_ACC_VAL) 40c17ca3f5SEric Andersson 41c17ca3f5SEric Andersson /* Each axis is represented by a 2-byte data word */ 42c17ca3f5SEric Andersson #define BMA150_XYZ_DATA_SIZE 6 43c17ca3f5SEric Andersson 44c17ca3f5SEric Andersson /* Input poll interval in milliseconds */ 45c17ca3f5SEric Andersson #define BMA150_POLL_INTERVAL 10 46c17ca3f5SEric Andersson #define BMA150_POLL_MAX 200 47c17ca3f5SEric Andersson #define BMA150_POLL_MIN 0 48c17ca3f5SEric Andersson 49c17ca3f5SEric Andersson #define BMA150_BW_25HZ 0 50c17ca3f5SEric Andersson #define BMA150_BW_50HZ 1 51c17ca3f5SEric Andersson #define BMA150_BW_100HZ 2 52c17ca3f5SEric Andersson #define BMA150_BW_190HZ 3 53c17ca3f5SEric Andersson #define BMA150_BW_375HZ 4 54c17ca3f5SEric Andersson #define BMA150_BW_750HZ 5 55c17ca3f5SEric Andersson #define BMA150_BW_1500HZ 6 56c17ca3f5SEric Andersson 57c17ca3f5SEric Andersson #define BMA150_RANGE_2G 0 58c17ca3f5SEric Andersson #define BMA150_RANGE_4G 1 59c17ca3f5SEric Andersson #define BMA150_RANGE_8G 2 60c17ca3f5SEric Andersson 61c17ca3f5SEric Andersson #define BMA150_MODE_NORMAL 0 62c17ca3f5SEric Andersson #define BMA150_MODE_SLEEP 2 63c17ca3f5SEric Andersson #define BMA150_MODE_WAKE_UP 3 64c17ca3f5SEric Andersson 65c17ca3f5SEric Andersson /* Data register addresses */ 66c17ca3f5SEric Andersson #define BMA150_DATA_0_REG 0x00 67c17ca3f5SEric Andersson #define BMA150_DATA_1_REG 0x01 68c17ca3f5SEric Andersson #define BMA150_DATA_2_REG 0x02 69c17ca3f5SEric Andersson 70c17ca3f5SEric Andersson /* Control register addresses */ 71c17ca3f5SEric Andersson #define BMA150_CTRL_0_REG 0x0A 72c17ca3f5SEric Andersson #define BMA150_CTRL_1_REG 0x0B 73c17ca3f5SEric Andersson #define BMA150_CTRL_2_REG 0x14 74c17ca3f5SEric Andersson #define BMA150_CTRL_3_REG 0x15 75c17ca3f5SEric Andersson 76c17ca3f5SEric Andersson /* Configuration/Setting register addresses */ 77c17ca3f5SEric Andersson #define BMA150_CFG_0_REG 0x0C 78c17ca3f5SEric Andersson #define BMA150_CFG_1_REG 0x0D 79c17ca3f5SEric Andersson #define BMA150_CFG_2_REG 0x0E 80c17ca3f5SEric Andersson #define BMA150_CFG_3_REG 0x0F 81c17ca3f5SEric Andersson #define BMA150_CFG_4_REG 0x10 82c17ca3f5SEric Andersson #define BMA150_CFG_5_REG 0x11 83c17ca3f5SEric Andersson 84c17ca3f5SEric Andersson #define BMA150_CHIP_ID 2 85c17ca3f5SEric Andersson #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG 86c17ca3f5SEric Andersson 87c17ca3f5SEric Andersson #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG 88c17ca3f5SEric Andersson 89c17ca3f5SEric Andersson #define BMA150_SLEEP_POS 0 90c17ca3f5SEric Andersson #define BMA150_SLEEP_MSK 0x01 91c17ca3f5SEric Andersson #define BMA150_SLEEP_REG BMA150_CTRL_0_REG 92c17ca3f5SEric Andersson 93c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_POS 0 94c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_MSK 0x07 95c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_REG BMA150_CTRL_2_REG 96c17ca3f5SEric Andersson 97c17ca3f5SEric Andersson #define BMA150_RANGE_POS 3 98c17ca3f5SEric Andersson #define BMA150_RANGE_MSK 0x18 99c17ca3f5SEric Andersson #define BMA150_RANGE_REG BMA150_CTRL_2_REG 100c17ca3f5SEric Andersson 101c17ca3f5SEric Andersson #define BMA150_WAKE_UP_POS 0 102c17ca3f5SEric Andersson #define BMA150_WAKE_UP_MSK 0x01 103c17ca3f5SEric Andersson #define BMA150_WAKE_UP_REG BMA150_CTRL_3_REG 104c17ca3f5SEric Andersson 105c17ca3f5SEric Andersson #define BMA150_SW_RES_POS 1 106c17ca3f5SEric Andersson #define BMA150_SW_RES_MSK 0x02 107c17ca3f5SEric Andersson #define BMA150_SW_RES_REG BMA150_CTRL_0_REG 108c17ca3f5SEric Andersson 109c17ca3f5SEric Andersson /* Any-motion interrupt register fields */ 110c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_POS 6 111c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_MSK 0x40 112c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_REG BMA150_CTRL_1_REG 113c17ca3f5SEric Andersson 114c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_POS 6 115c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_MSK 0xC0 116c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_REG BMA150_CFG_5_REG 117c17ca3f5SEric Andersson 118c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_THRES_REG BMA150_CFG_4_REG 119c17ca3f5SEric Andersson 120c17ca3f5SEric Andersson /* Advanced interrupt register fields */ 121c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_POS 6 122c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_MSK 0x40 123c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_REG BMA150_CTRL_3_REG 124c17ca3f5SEric Andersson 125c17ca3f5SEric Andersson /* High-G interrupt register fields */ 126c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_POS 1 127c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_MSK 0x02 128c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_REG BMA150_CTRL_1_REG 129c17ca3f5SEric Andersson 130c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_POS 3 131c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_MSK 0x38 132c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_REG BMA150_CFG_5_REG 133c17ca3f5SEric Andersson 134c17ca3f5SEric Andersson #define BMA150_HIGH_G_DUR_REG BMA150_CFG_3_REG 135c17ca3f5SEric Andersson #define BMA150_HIGH_G_THRES_REG BMA150_CFG_2_REG 136c17ca3f5SEric Andersson 137c17ca3f5SEric Andersson /* Low-G interrupt register fields */ 138c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_POS 0 139c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_MSK 0x01 140c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_REG BMA150_CTRL_1_REG 141c17ca3f5SEric Andersson 142c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_POS 0 143c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_MSK 0x07 144c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_REG BMA150_CFG_5_REG 145c17ca3f5SEric Andersson 146c17ca3f5SEric Andersson #define BMA150_LOW_G_DUR_REG BMA150_CFG_1_REG 147c17ca3f5SEric Andersson #define BMA150_LOW_G_THRES_REG BMA150_CFG_0_REG 148c17ca3f5SEric Andersson 149c17ca3f5SEric Andersson struct bma150_data { 150c17ca3f5SEric Andersson struct i2c_client *client; 151c17ca3f5SEric Andersson struct input_polled_dev *input_polled; 152c17ca3f5SEric Andersson struct input_dev *input; 153c17ca3f5SEric Andersson u8 mode; 154c17ca3f5SEric Andersson }; 155c17ca3f5SEric Andersson 156c17ca3f5SEric Andersson /* 157c17ca3f5SEric Andersson * The settings for the given range, bandwidth and interrupt features 158c17ca3f5SEric Andersson * are stated and verified by Bosch Sensortec where they are configured 159c17ca3f5SEric Andersson * to provide a generic sensitivity performance. 160c17ca3f5SEric Andersson */ 161c17ca3f5SEric Andersson static struct bma150_cfg default_cfg __devinitdata = { 162c17ca3f5SEric Andersson .any_motion_int = 1, 163c17ca3f5SEric Andersson .hg_int = 1, 164c17ca3f5SEric Andersson .lg_int = 1, 165c17ca3f5SEric Andersson .any_motion_dur = 0, 166c17ca3f5SEric Andersson .any_motion_thres = 0, 167c17ca3f5SEric Andersson .hg_hyst = 0, 168c17ca3f5SEric Andersson .hg_dur = 150, 169c17ca3f5SEric Andersson .hg_thres = 160, 170c17ca3f5SEric Andersson .lg_hyst = 0, 171c17ca3f5SEric Andersson .lg_dur = 150, 172c17ca3f5SEric Andersson .lg_thres = 20, 173c17ca3f5SEric Andersson .range = BMA150_RANGE_2G, 174c17ca3f5SEric Andersson .bandwidth = BMA150_BW_50HZ 175c17ca3f5SEric Andersson }; 176c17ca3f5SEric Andersson 177c17ca3f5SEric Andersson static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val) 178c17ca3f5SEric Andersson { 179c17ca3f5SEric Andersson s32 ret; 180c17ca3f5SEric Andersson 181c17ca3f5SEric Andersson /* As per specification, disable irq in between register writes */ 182c17ca3f5SEric Andersson if (client->irq) 183c17ca3f5SEric Andersson disable_irq_nosync(client->irq); 184c17ca3f5SEric Andersson 185c17ca3f5SEric Andersson ret = i2c_smbus_write_byte_data(client, reg, val); 186c17ca3f5SEric Andersson 187c17ca3f5SEric Andersson if (client->irq) 188c17ca3f5SEric Andersson enable_irq(client->irq); 189c17ca3f5SEric Andersson 190c17ca3f5SEric Andersson return ret; 191c17ca3f5SEric Andersson } 192c17ca3f5SEric Andersson 193c17ca3f5SEric Andersson static int bma150_set_reg_bits(struct i2c_client *client, 194c17ca3f5SEric Andersson int val, int shift, u8 mask, u8 reg) 195c17ca3f5SEric Andersson { 196c17ca3f5SEric Andersson int data; 197c17ca3f5SEric Andersson 198c17ca3f5SEric Andersson data = i2c_smbus_read_byte_data(client, reg); 199c17ca3f5SEric Andersson if (data < 0) 200c17ca3f5SEric Andersson return data; 201c17ca3f5SEric Andersson 202c17ca3f5SEric Andersson data = (data & ~mask) | ((val << shift) & mask); 203c17ca3f5SEric Andersson return bma150_write_byte(client, reg, data); 204c17ca3f5SEric Andersson } 205c17ca3f5SEric Andersson 206c17ca3f5SEric Andersson static int bma150_set_mode(struct bma150_data *bma150, u8 mode) 207c17ca3f5SEric Andersson { 208c17ca3f5SEric Andersson int error; 209c17ca3f5SEric Andersson 210c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS, 211c17ca3f5SEric Andersson BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG); 212c17ca3f5SEric Andersson if (error) 213c17ca3f5SEric Andersson return error; 214c17ca3f5SEric Andersson 215c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS, 216c17ca3f5SEric Andersson BMA150_SLEEP_MSK, BMA150_SLEEP_REG); 217c17ca3f5SEric Andersson if (error) 218c17ca3f5SEric Andersson return error; 219c17ca3f5SEric Andersson 220c17ca3f5SEric Andersson if (mode == BMA150_MODE_NORMAL) 221c17ca3f5SEric Andersson msleep(2); 222c17ca3f5SEric Andersson 223c17ca3f5SEric Andersson bma150->mode = mode; 224c17ca3f5SEric Andersson return 0; 225c17ca3f5SEric Andersson } 226c17ca3f5SEric Andersson 227c17ca3f5SEric Andersson static int __devinit bma150_soft_reset(struct bma150_data *bma150) 228c17ca3f5SEric Andersson { 229c17ca3f5SEric Andersson int error; 230c17ca3f5SEric Andersson 231c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS, 232c17ca3f5SEric Andersson BMA150_SW_RES_MSK, BMA150_SW_RES_REG); 233c17ca3f5SEric Andersson if (error) 234c17ca3f5SEric Andersson return error; 235c17ca3f5SEric Andersson 236c17ca3f5SEric Andersson msleep(2); 237c17ca3f5SEric Andersson return 0; 238c17ca3f5SEric Andersson } 239c17ca3f5SEric Andersson 240c17ca3f5SEric Andersson static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range) 241c17ca3f5SEric Andersson { 242c17ca3f5SEric Andersson return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS, 243c17ca3f5SEric Andersson BMA150_RANGE_MSK, BMA150_RANGE_REG); 244c17ca3f5SEric Andersson } 245c17ca3f5SEric Andersson 246c17ca3f5SEric Andersson static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw) 247c17ca3f5SEric Andersson { 248c17ca3f5SEric Andersson return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS, 249c17ca3f5SEric Andersson BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG); 250c17ca3f5SEric Andersson } 251c17ca3f5SEric Andersson 252c17ca3f5SEric Andersson static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150, 253c17ca3f5SEric Andersson u8 enable, u8 hyst, u8 dur, u8 thres) 254c17ca3f5SEric Andersson { 255c17ca3f5SEric Andersson int error; 256c17ca3f5SEric Andersson 257c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, hyst, 258c17ca3f5SEric Andersson BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK, 259c17ca3f5SEric Andersson BMA150_LOW_G_HYST_REG); 260c17ca3f5SEric Andersson if (error) 261c17ca3f5SEric Andersson return error; 262c17ca3f5SEric Andersson 263c17ca3f5SEric Andersson error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur); 264c17ca3f5SEric Andersson if (error) 265c17ca3f5SEric Andersson return error; 266c17ca3f5SEric Andersson 267c17ca3f5SEric Andersson error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres); 268c17ca3f5SEric Andersson if (error) 269c17ca3f5SEric Andersson return error; 270c17ca3f5SEric Andersson 271c17ca3f5SEric Andersson return bma150_set_reg_bits(bma150->client, !!enable, 272c17ca3f5SEric Andersson BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK, 273c17ca3f5SEric Andersson BMA150_LOW_G_EN_REG); 274c17ca3f5SEric Andersson } 275c17ca3f5SEric Andersson 276c17ca3f5SEric Andersson static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150, 277c17ca3f5SEric Andersson u8 enable, u8 hyst, u8 dur, u8 thres) 278c17ca3f5SEric Andersson { 279c17ca3f5SEric Andersson int error; 280c17ca3f5SEric Andersson 281c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, hyst, 282c17ca3f5SEric Andersson BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK, 283c17ca3f5SEric Andersson BMA150_HIGH_G_HYST_REG); 284c17ca3f5SEric Andersson if (error) 285c17ca3f5SEric Andersson return error; 286c17ca3f5SEric Andersson 287c17ca3f5SEric Andersson error = bma150_write_byte(bma150->client, 288c17ca3f5SEric Andersson BMA150_HIGH_G_DUR_REG, dur); 289c17ca3f5SEric Andersson if (error) 290c17ca3f5SEric Andersson return error; 291c17ca3f5SEric Andersson 292c17ca3f5SEric Andersson error = bma150_write_byte(bma150->client, 293c17ca3f5SEric Andersson BMA150_HIGH_G_THRES_REG, thres); 294c17ca3f5SEric Andersson if (error) 295c17ca3f5SEric Andersson return error; 296c17ca3f5SEric Andersson 297c17ca3f5SEric Andersson return bma150_set_reg_bits(bma150->client, !!enable, 298c17ca3f5SEric Andersson BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK, 299c17ca3f5SEric Andersson BMA150_HIGH_G_EN_REG); 300c17ca3f5SEric Andersson } 301c17ca3f5SEric Andersson 302c17ca3f5SEric Andersson 303c17ca3f5SEric Andersson static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150, 304c17ca3f5SEric Andersson u8 enable, u8 dur, u8 thres) 305c17ca3f5SEric Andersson { 306c17ca3f5SEric Andersson int error; 307c17ca3f5SEric Andersson 308c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, dur, 309c17ca3f5SEric Andersson BMA150_ANY_MOTION_DUR_POS, 310c17ca3f5SEric Andersson BMA150_ANY_MOTION_DUR_MSK, 311c17ca3f5SEric Andersson BMA150_ANY_MOTION_DUR_REG); 312c17ca3f5SEric Andersson if (error) 313c17ca3f5SEric Andersson return error; 314c17ca3f5SEric Andersson 315c17ca3f5SEric Andersson error = bma150_write_byte(bma150->client, 316c17ca3f5SEric Andersson BMA150_ANY_MOTION_THRES_REG, thres); 317c17ca3f5SEric Andersson if (error) 318c17ca3f5SEric Andersson return error; 319c17ca3f5SEric Andersson 320c17ca3f5SEric Andersson error = bma150_set_reg_bits(bma150->client, !!enable, 321c17ca3f5SEric Andersson BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK, 322c17ca3f5SEric Andersson BMA150_ADV_INT_EN_REG); 323c17ca3f5SEric Andersson if (error) 324c17ca3f5SEric Andersson return error; 325c17ca3f5SEric Andersson 326c17ca3f5SEric Andersson return bma150_set_reg_bits(bma150->client, !!enable, 327c17ca3f5SEric Andersson BMA150_ANY_MOTION_EN_POS, 328c17ca3f5SEric Andersson BMA150_ANY_MOTION_EN_MSK, 329c17ca3f5SEric Andersson BMA150_ANY_MOTION_EN_REG); 330c17ca3f5SEric Andersson } 331c17ca3f5SEric Andersson 332c17ca3f5SEric Andersson static void bma150_report_xyz(struct bma150_data *bma150) 333c17ca3f5SEric Andersson { 334c17ca3f5SEric Andersson u8 data[BMA150_XYZ_DATA_SIZE]; 335c17ca3f5SEric Andersson s16 x, y, z; 336c17ca3f5SEric Andersson s32 ret; 337c17ca3f5SEric Andersson 338c17ca3f5SEric Andersson ret = i2c_smbus_read_i2c_block_data(bma150->client, 339c17ca3f5SEric Andersson BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data); 340c17ca3f5SEric Andersson if (ret != BMA150_XYZ_DATA_SIZE) 341c17ca3f5SEric Andersson return; 342c17ca3f5SEric Andersson 343c17ca3f5SEric Andersson x = ((0xc0 & data[0]) >> 6) | (data[1] << 2); 344c17ca3f5SEric Andersson y = ((0xc0 & data[2]) >> 6) | (data[3] << 2); 345c17ca3f5SEric Andersson z = ((0xc0 & data[4]) >> 6) | (data[5] << 2); 346c17ca3f5SEric Andersson 347c17ca3f5SEric Andersson /* sign extension */ 348c17ca3f5SEric Andersson x = (s16) (x << 6) >> 6; 349c17ca3f5SEric Andersson y = (s16) (y << 6) >> 6; 350c17ca3f5SEric Andersson z = (s16) (z << 6) >> 6; 351c17ca3f5SEric Andersson 352c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_X, x); 353c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_Y, y); 354c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_Z, z); 355c17ca3f5SEric Andersson input_sync(bma150->input); 356c17ca3f5SEric Andersson } 357c17ca3f5SEric Andersson 358c17ca3f5SEric Andersson static irqreturn_t bma150_irq_thread(int irq, void *dev) 359c17ca3f5SEric Andersson { 360c17ca3f5SEric Andersson bma150_report_xyz(dev); 361c17ca3f5SEric Andersson 362c17ca3f5SEric Andersson return IRQ_HANDLED; 363c17ca3f5SEric Andersson } 364c17ca3f5SEric Andersson 365c17ca3f5SEric Andersson static void bma150_poll(struct input_polled_dev *dev) 366c17ca3f5SEric Andersson { 367c17ca3f5SEric Andersson bma150_report_xyz(dev->private); 368c17ca3f5SEric Andersson } 369c17ca3f5SEric Andersson 370c17ca3f5SEric Andersson static int bma150_open(struct bma150_data *bma150) 371c17ca3f5SEric Andersson { 372c17ca3f5SEric Andersson int error; 373c17ca3f5SEric Andersson 374c17ca3f5SEric Andersson error = pm_runtime_get_sync(&bma150->client->dev); 375c17ca3f5SEric Andersson if (error && error != -ENOSYS) 376c17ca3f5SEric Andersson return error; 377c17ca3f5SEric Andersson 378c17ca3f5SEric Andersson /* 379c17ca3f5SEric Andersson * See if runtime PM woke up the device. If runtime PM 380c17ca3f5SEric Andersson * is disabled we need to do it ourselves. 381c17ca3f5SEric Andersson */ 382c17ca3f5SEric Andersson if (bma150->mode != BMA150_MODE_NORMAL) { 383c17ca3f5SEric Andersson error = bma150_set_mode(bma150, BMA150_MODE_NORMAL); 384c17ca3f5SEric Andersson if (error) 385c17ca3f5SEric Andersson return error; 386c17ca3f5SEric Andersson } 387c17ca3f5SEric Andersson 388c17ca3f5SEric Andersson return 0; 389c17ca3f5SEric Andersson } 390c17ca3f5SEric Andersson 391c17ca3f5SEric Andersson static void bma150_close(struct bma150_data *bma150) 392c17ca3f5SEric Andersson { 393c17ca3f5SEric Andersson pm_runtime_put_sync(&bma150->client->dev); 394c17ca3f5SEric Andersson 395c17ca3f5SEric Andersson if (bma150->mode != BMA150_MODE_SLEEP) 396c17ca3f5SEric Andersson bma150_set_mode(bma150, BMA150_MODE_SLEEP); 397c17ca3f5SEric Andersson } 398c17ca3f5SEric Andersson 399c17ca3f5SEric Andersson static int bma150_irq_open(struct input_dev *input) 400c17ca3f5SEric Andersson { 401c17ca3f5SEric Andersson struct bma150_data *bma150 = input_get_drvdata(input); 402c17ca3f5SEric Andersson 403c17ca3f5SEric Andersson return bma150_open(bma150); 404c17ca3f5SEric Andersson } 405c17ca3f5SEric Andersson 406c17ca3f5SEric Andersson static void bma150_irq_close(struct input_dev *input) 407c17ca3f5SEric Andersson { 408c17ca3f5SEric Andersson struct bma150_data *bma150 = input_get_drvdata(input); 409c17ca3f5SEric Andersson 410c17ca3f5SEric Andersson bma150_close(bma150); 411c17ca3f5SEric Andersson } 412c17ca3f5SEric Andersson 413c17ca3f5SEric Andersson static void bma150_poll_open(struct input_polled_dev *ipoll_dev) 414c17ca3f5SEric Andersson { 415c17ca3f5SEric Andersson struct bma150_data *bma150 = ipoll_dev->private; 416c17ca3f5SEric Andersson 417c17ca3f5SEric Andersson bma150_open(bma150); 418c17ca3f5SEric Andersson } 419c17ca3f5SEric Andersson 420c17ca3f5SEric Andersson static void bma150_poll_close(struct input_polled_dev *ipoll_dev) 421c17ca3f5SEric Andersson { 422c17ca3f5SEric Andersson struct bma150_data *bma150 = ipoll_dev->private; 423c17ca3f5SEric Andersson 424c17ca3f5SEric Andersson bma150_close(bma150); 425c17ca3f5SEric Andersson } 426c17ca3f5SEric Andersson 427c17ca3f5SEric Andersson static int __devinit bma150_initialize(struct bma150_data *bma150, 428c17ca3f5SEric Andersson const struct bma150_cfg *cfg) 429c17ca3f5SEric Andersson { 430c17ca3f5SEric Andersson int error; 431c17ca3f5SEric Andersson 432c17ca3f5SEric Andersson error = bma150_soft_reset(bma150); 433c17ca3f5SEric Andersson if (error) 434c17ca3f5SEric Andersson return error; 435c17ca3f5SEric Andersson 436c17ca3f5SEric Andersson error = bma150_set_bandwidth(bma150, cfg->bandwidth); 437c17ca3f5SEric Andersson if (error) 438c17ca3f5SEric Andersson return error; 439c17ca3f5SEric Andersson 440c17ca3f5SEric Andersson error = bma150_set_range(bma150, cfg->range); 441c17ca3f5SEric Andersson if (error) 442c17ca3f5SEric Andersson return error; 443c17ca3f5SEric Andersson 444c17ca3f5SEric Andersson if (bma150->client->irq) { 445c17ca3f5SEric Andersson error = bma150_set_any_motion_interrupt(bma150, 446c17ca3f5SEric Andersson cfg->any_motion_int, 447c17ca3f5SEric Andersson cfg->any_motion_dur, 448c17ca3f5SEric Andersson cfg->any_motion_thres); 449c17ca3f5SEric Andersson if (error) 450c17ca3f5SEric Andersson return error; 451c17ca3f5SEric Andersson 452c17ca3f5SEric Andersson error = bma150_set_high_g_interrupt(bma150, 453c17ca3f5SEric Andersson cfg->hg_int, cfg->hg_hyst, 454c17ca3f5SEric Andersson cfg->hg_dur, cfg->hg_thres); 455c17ca3f5SEric Andersson if (error) 456c17ca3f5SEric Andersson return error; 457c17ca3f5SEric Andersson 458c17ca3f5SEric Andersson error = bma150_set_low_g_interrupt(bma150, 459c17ca3f5SEric Andersson cfg->lg_int, cfg->lg_hyst, 460c17ca3f5SEric Andersson cfg->lg_dur, cfg->lg_thres); 461c17ca3f5SEric Andersson if (error) 462c17ca3f5SEric Andersson return error; 463c17ca3f5SEric Andersson } 464c17ca3f5SEric Andersson 465c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_SLEEP); 466c17ca3f5SEric Andersson } 467c17ca3f5SEric Andersson 468c17ca3f5SEric Andersson static void __devinit bma150_init_input_device(struct bma150_data *bma150, 469c17ca3f5SEric Andersson struct input_dev *idev) 470c17ca3f5SEric Andersson { 471c17ca3f5SEric Andersson idev->name = BMA150_DRIVER; 472c17ca3f5SEric Andersson idev->phys = BMA150_DRIVER "/input0"; 473c17ca3f5SEric Andersson idev->id.bustype = BUS_I2C; 474c17ca3f5SEric Andersson idev->dev.parent = &bma150->client->dev; 475c17ca3f5SEric Andersson 476c17ca3f5SEric Andersson idev->evbit[0] = BIT_MASK(EV_ABS); 477c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 478c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 479c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 480c17ca3f5SEric Andersson } 481c17ca3f5SEric Andersson 482c17ca3f5SEric Andersson static int __devinit bma150_register_input_device(struct bma150_data *bma150) 483c17ca3f5SEric Andersson { 484c17ca3f5SEric Andersson struct input_dev *idev; 485c17ca3f5SEric Andersson int error; 486c17ca3f5SEric Andersson 487c17ca3f5SEric Andersson idev = input_allocate_device(); 488c17ca3f5SEric Andersson if (!idev) 489c17ca3f5SEric Andersson return -ENOMEM; 490c17ca3f5SEric Andersson 491c17ca3f5SEric Andersson bma150_init_input_device(bma150, idev); 492c17ca3f5SEric Andersson 493c17ca3f5SEric Andersson idev->open = bma150_irq_open; 494c17ca3f5SEric Andersson idev->close = bma150_irq_close; 495c17ca3f5SEric Andersson input_set_drvdata(idev, bma150); 496c17ca3f5SEric Andersson 497c17ca3f5SEric Andersson error = input_register_device(idev); 498c17ca3f5SEric Andersson if (error) { 499c17ca3f5SEric Andersson input_free_device(idev); 500c17ca3f5SEric Andersson return error; 501c17ca3f5SEric Andersson } 502c17ca3f5SEric Andersson 503c17ca3f5SEric Andersson bma150->input = idev; 504c17ca3f5SEric Andersson return 0; 505c17ca3f5SEric Andersson } 506c17ca3f5SEric Andersson 507c17ca3f5SEric Andersson static int __devinit bma150_register_polled_device(struct bma150_data *bma150) 508c17ca3f5SEric Andersson { 509c17ca3f5SEric Andersson struct input_polled_dev *ipoll_dev; 510c17ca3f5SEric Andersson int error; 511c17ca3f5SEric Andersson 512c17ca3f5SEric Andersson ipoll_dev = input_allocate_polled_device(); 513c17ca3f5SEric Andersson if (!ipoll_dev) 514c17ca3f5SEric Andersson return -ENOMEM; 515c17ca3f5SEric Andersson 516c17ca3f5SEric Andersson ipoll_dev->private = bma150; 517c17ca3f5SEric Andersson ipoll_dev->open = bma150_poll_open; 518c17ca3f5SEric Andersson ipoll_dev->close = bma150_poll_close; 519c17ca3f5SEric Andersson ipoll_dev->poll = bma150_poll; 520c17ca3f5SEric Andersson ipoll_dev->poll_interval = BMA150_POLL_INTERVAL; 521c17ca3f5SEric Andersson ipoll_dev->poll_interval_min = BMA150_POLL_MIN; 522c17ca3f5SEric Andersson ipoll_dev->poll_interval_max = BMA150_POLL_MAX; 523c17ca3f5SEric Andersson 524c17ca3f5SEric Andersson bma150_init_input_device(bma150, ipoll_dev->input); 525c17ca3f5SEric Andersson 526c17ca3f5SEric Andersson error = input_register_polled_device(ipoll_dev); 527c17ca3f5SEric Andersson if (error) { 528c17ca3f5SEric Andersson input_free_polled_device(ipoll_dev); 529c17ca3f5SEric Andersson return error; 530c17ca3f5SEric Andersson } 531c17ca3f5SEric Andersson 532c17ca3f5SEric Andersson bma150->input_polled = ipoll_dev; 533c17ca3f5SEric Andersson bma150->input = ipoll_dev->input; 534c17ca3f5SEric Andersson 535c17ca3f5SEric Andersson return 0; 536c17ca3f5SEric Andersson } 537c17ca3f5SEric Andersson 538c17ca3f5SEric Andersson static int __devinit bma150_probe(struct i2c_client *client, 539c17ca3f5SEric Andersson const struct i2c_device_id *id) 540c17ca3f5SEric Andersson { 541c17ca3f5SEric Andersson const struct bma150_platform_data *pdata = client->dev.platform_data; 542c17ca3f5SEric Andersson const struct bma150_cfg *cfg; 543c17ca3f5SEric Andersson struct bma150_data *bma150; 544c17ca3f5SEric Andersson int chip_id; 545c17ca3f5SEric Andersson int error; 546c17ca3f5SEric Andersson 547c17ca3f5SEric Andersson if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 548c17ca3f5SEric Andersson dev_err(&client->dev, "i2c_check_functionality error\n"); 549c17ca3f5SEric Andersson return -EIO; 550c17ca3f5SEric Andersson } 551c17ca3f5SEric Andersson 552c17ca3f5SEric Andersson chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); 553c17ca3f5SEric Andersson if (chip_id != BMA150_CHIP_ID) { 554c17ca3f5SEric Andersson dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); 555c17ca3f5SEric Andersson return -EINVAL; 556c17ca3f5SEric Andersson } 557c17ca3f5SEric Andersson 558c17ca3f5SEric Andersson bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); 559c17ca3f5SEric Andersson if (!bma150) 560c17ca3f5SEric Andersson return -ENOMEM; 561c17ca3f5SEric Andersson 562c17ca3f5SEric Andersson bma150->client = client; 563c17ca3f5SEric Andersson 564c17ca3f5SEric Andersson if (pdata) { 565c17ca3f5SEric Andersson if (pdata->irq_gpio_cfg) { 566c17ca3f5SEric Andersson error = pdata->irq_gpio_cfg(); 567c17ca3f5SEric Andersson if (error) { 568c17ca3f5SEric Andersson dev_err(&client->dev, 569c17ca3f5SEric Andersson "IRQ GPIO conf. error %d, error %d\n", 570c17ca3f5SEric Andersson client->irq, error); 571c17ca3f5SEric Andersson goto err_free_mem; 572c17ca3f5SEric Andersson } 573c17ca3f5SEric Andersson } 574c17ca3f5SEric Andersson cfg = &pdata->cfg; 575c17ca3f5SEric Andersson } else { 576c17ca3f5SEric Andersson cfg = &default_cfg; 577c17ca3f5SEric Andersson } 578c17ca3f5SEric Andersson 579c17ca3f5SEric Andersson error = bma150_initialize(bma150, cfg); 580c17ca3f5SEric Andersson if (error) 581c17ca3f5SEric Andersson goto err_free_mem; 582c17ca3f5SEric Andersson 583c17ca3f5SEric Andersson if (client->irq > 0) { 584c17ca3f5SEric Andersson error = bma150_register_input_device(bma150); 585c17ca3f5SEric Andersson if (error) 586c17ca3f5SEric Andersson goto err_free_mem; 587c17ca3f5SEric Andersson 588c17ca3f5SEric Andersson error = request_threaded_irq(client->irq, 589c17ca3f5SEric Andersson NULL, bma150_irq_thread, 590c17ca3f5SEric Andersson IRQF_TRIGGER_RISING | IRQF_ONESHOT, 591c17ca3f5SEric Andersson BMA150_DRIVER, bma150); 592c17ca3f5SEric Andersson if (error) { 593c17ca3f5SEric Andersson dev_err(&client->dev, 594c17ca3f5SEric Andersson "irq request failed %d, error %d\n", 595c17ca3f5SEric Andersson client->irq, error); 596c17ca3f5SEric Andersson input_unregister_device(bma150->input); 597c17ca3f5SEric Andersson goto err_free_mem; 598c17ca3f5SEric Andersson } 599c17ca3f5SEric Andersson } else { 600c17ca3f5SEric Andersson error = bma150_register_polled_device(bma150); 601c17ca3f5SEric Andersson if (error) 602c17ca3f5SEric Andersson goto err_free_mem; 603c17ca3f5SEric Andersson } 604c17ca3f5SEric Andersson 605c17ca3f5SEric Andersson i2c_set_clientdata(client, bma150); 606c17ca3f5SEric Andersson 607c17ca3f5SEric Andersson pm_runtime_enable(&client->dev); 608c17ca3f5SEric Andersson 609c17ca3f5SEric Andersson return 0; 610c17ca3f5SEric Andersson 611c17ca3f5SEric Andersson err_free_mem: 612c17ca3f5SEric Andersson kfree(bma150); 613c17ca3f5SEric Andersson return error; 614c17ca3f5SEric Andersson } 615c17ca3f5SEric Andersson 616c17ca3f5SEric Andersson static int __devexit bma150_remove(struct i2c_client *client) 617c17ca3f5SEric Andersson { 618c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 619c17ca3f5SEric Andersson 620c17ca3f5SEric Andersson pm_runtime_disable(&client->dev); 621c17ca3f5SEric Andersson 622c17ca3f5SEric Andersson if (client->irq > 0) { 623c17ca3f5SEric Andersson free_irq(client->irq, bma150); 624c17ca3f5SEric Andersson input_unregister_device(bma150->input); 625c17ca3f5SEric Andersson } else { 626c17ca3f5SEric Andersson input_unregister_polled_device(bma150->input_polled); 627c17ca3f5SEric Andersson input_free_polled_device(bma150->input_polled); 628c17ca3f5SEric Andersson } 629c17ca3f5SEric Andersson 630c17ca3f5SEric Andersson kfree(bma150); 631c17ca3f5SEric Andersson 632c17ca3f5SEric Andersson return 0; 633c17ca3f5SEric Andersson } 634c17ca3f5SEric Andersson 635c17ca3f5SEric Andersson #ifdef CONFIG_PM 636c17ca3f5SEric Andersson static int bma150_suspend(struct device *dev) 637c17ca3f5SEric Andersson { 638c17ca3f5SEric Andersson struct i2c_client *client = to_i2c_client(dev); 639c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 640c17ca3f5SEric Andersson 641c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_SLEEP); 642c17ca3f5SEric Andersson } 643c17ca3f5SEric Andersson 644c17ca3f5SEric Andersson static int bma150_resume(struct device *dev) 645c17ca3f5SEric Andersson { 646c17ca3f5SEric Andersson struct i2c_client *client = to_i2c_client(dev); 647c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 648c17ca3f5SEric Andersson 649c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_NORMAL); 650c17ca3f5SEric Andersson } 651c17ca3f5SEric Andersson #endif 652c17ca3f5SEric Andersson 653c17ca3f5SEric Andersson static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); 654c17ca3f5SEric Andersson 655c17ca3f5SEric Andersson static const struct i2c_device_id bma150_id[] = { 656c17ca3f5SEric Andersson { "bma150", 0 }, 657c17ca3f5SEric Andersson { "smb380", 0 }, 658c17ca3f5SEric Andersson { "bma023", 0 }, 659c17ca3f5SEric Andersson { } 660c17ca3f5SEric Andersson }; 661c17ca3f5SEric Andersson 662c17ca3f5SEric Andersson MODULE_DEVICE_TABLE(i2c, bma150_id); 663c17ca3f5SEric Andersson 664c17ca3f5SEric Andersson static struct i2c_driver bma150_driver = { 665c17ca3f5SEric Andersson .driver = { 666c17ca3f5SEric Andersson .owner = THIS_MODULE, 667c17ca3f5SEric Andersson .name = BMA150_DRIVER, 668c17ca3f5SEric Andersson .pm = &bma150_pm, 669c17ca3f5SEric Andersson }, 670c17ca3f5SEric Andersson .class = I2C_CLASS_HWMON, 671c17ca3f5SEric Andersson .id_table = bma150_id, 672c17ca3f5SEric Andersson .probe = bma150_probe, 673c17ca3f5SEric Andersson .remove = __devexit_p(bma150_remove), 674c17ca3f5SEric Andersson }; 675c17ca3f5SEric Andersson 6761b92c1cfSAxel Lin module_i2c_driver(bma150_driver); 677c17ca3f5SEric Andersson 678c17ca3f5SEric Andersson MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>"); 679c17ca3f5SEric Andersson MODULE_DESCRIPTION("BMA150 driver"); 680c17ca3f5SEric Andersson MODULE_LICENSE("GPL"); 681