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