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 */ 1507ed5ff82SJulia Lawall static const 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) 210f63bb4f4SAniroop Mathur usleep_range(2000, 2100); 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 225f63bb4f4SAniroop Mathur usleep_range(2000, 2100); 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 336b7e79329SMartin Kepplinger x = sign_extend32(x, 9); 337b7e79329SMartin Kepplinger y = sign_extend32(y, 9); 338b7e79329SMartin Kepplinger z = sign_extend32(z, 9); 339c17ca3f5SEric Andersson 340c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_X, x); 341c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_Y, y); 342c17ca3f5SEric Andersson input_report_abs(bma150->input, ABS_Z, z); 343c17ca3f5SEric Andersson input_sync(bma150->input); 344c17ca3f5SEric Andersson } 345c17ca3f5SEric Andersson 346c17ca3f5SEric Andersson static irqreturn_t bma150_irq_thread(int irq, void *dev) 347c17ca3f5SEric Andersson { 348c17ca3f5SEric Andersson bma150_report_xyz(dev); 349c17ca3f5SEric Andersson 350c17ca3f5SEric Andersson return IRQ_HANDLED; 351c17ca3f5SEric Andersson } 352c17ca3f5SEric Andersson 353c17ca3f5SEric Andersson static void bma150_poll(struct input_polled_dev *dev) 354c17ca3f5SEric Andersson { 355c17ca3f5SEric Andersson bma150_report_xyz(dev->private); 356c17ca3f5SEric Andersson } 357c17ca3f5SEric Andersson 358c17ca3f5SEric Andersson static int bma150_open(struct bma150_data *bma150) 359c17ca3f5SEric Andersson { 360c17ca3f5SEric Andersson int error; 361c17ca3f5SEric Andersson 362c17ca3f5SEric Andersson error = pm_runtime_get_sync(&bma150->client->dev); 36379f34d19SMichael Trimarchi if (error < 0 && error != -ENOSYS) 364c17ca3f5SEric Andersson return error; 365c17ca3f5SEric Andersson 366c17ca3f5SEric Andersson /* 367c17ca3f5SEric Andersson * See if runtime PM woke up the device. If runtime PM 368c17ca3f5SEric Andersson * is disabled we need to do it ourselves. 369c17ca3f5SEric Andersson */ 370c17ca3f5SEric Andersson if (bma150->mode != BMA150_MODE_NORMAL) { 371c17ca3f5SEric Andersson error = bma150_set_mode(bma150, BMA150_MODE_NORMAL); 372c17ca3f5SEric Andersson if (error) 373c17ca3f5SEric Andersson return error; 374c17ca3f5SEric Andersson } 375c17ca3f5SEric Andersson 376c17ca3f5SEric Andersson return 0; 377c17ca3f5SEric Andersson } 378c17ca3f5SEric Andersson 379c17ca3f5SEric Andersson static void bma150_close(struct bma150_data *bma150) 380c17ca3f5SEric Andersson { 381c17ca3f5SEric Andersson pm_runtime_put_sync(&bma150->client->dev); 382c17ca3f5SEric Andersson 383c17ca3f5SEric Andersson if (bma150->mode != BMA150_MODE_SLEEP) 384c17ca3f5SEric Andersson bma150_set_mode(bma150, BMA150_MODE_SLEEP); 385c17ca3f5SEric Andersson } 386c17ca3f5SEric Andersson 387c17ca3f5SEric Andersson static int bma150_irq_open(struct input_dev *input) 388c17ca3f5SEric Andersson { 389c17ca3f5SEric Andersson struct bma150_data *bma150 = input_get_drvdata(input); 390c17ca3f5SEric Andersson 391c17ca3f5SEric Andersson return bma150_open(bma150); 392c17ca3f5SEric Andersson } 393c17ca3f5SEric Andersson 394c17ca3f5SEric Andersson static void bma150_irq_close(struct input_dev *input) 395c17ca3f5SEric Andersson { 396c17ca3f5SEric Andersson struct bma150_data *bma150 = input_get_drvdata(input); 397c17ca3f5SEric Andersson 398c17ca3f5SEric Andersson bma150_close(bma150); 399c17ca3f5SEric Andersson } 400c17ca3f5SEric Andersson 401c17ca3f5SEric Andersson static void bma150_poll_open(struct input_polled_dev *ipoll_dev) 402c17ca3f5SEric Andersson { 403c17ca3f5SEric Andersson struct bma150_data *bma150 = ipoll_dev->private; 404c17ca3f5SEric Andersson 405c17ca3f5SEric Andersson bma150_open(bma150); 406c17ca3f5SEric Andersson } 407c17ca3f5SEric Andersson 408c17ca3f5SEric Andersson static void bma150_poll_close(struct input_polled_dev *ipoll_dev) 409c17ca3f5SEric Andersson { 410c17ca3f5SEric Andersson struct bma150_data *bma150 = ipoll_dev->private; 411c17ca3f5SEric Andersson 412c17ca3f5SEric Andersson bma150_close(bma150); 413c17ca3f5SEric Andersson } 414c17ca3f5SEric Andersson 4155298cc4cSBill Pemberton static int bma150_initialize(struct bma150_data *bma150, 416c17ca3f5SEric Andersson const struct bma150_cfg *cfg) 417c17ca3f5SEric Andersson { 418c17ca3f5SEric Andersson int error; 419c17ca3f5SEric Andersson 420c17ca3f5SEric Andersson error = bma150_soft_reset(bma150); 421c17ca3f5SEric Andersson if (error) 422c17ca3f5SEric Andersson return error; 423c17ca3f5SEric Andersson 424c17ca3f5SEric Andersson error = bma150_set_bandwidth(bma150, cfg->bandwidth); 425c17ca3f5SEric Andersson if (error) 426c17ca3f5SEric Andersson return error; 427c17ca3f5SEric Andersson 428c17ca3f5SEric Andersson error = bma150_set_range(bma150, cfg->range); 429c17ca3f5SEric Andersson if (error) 430c17ca3f5SEric Andersson return error; 431c17ca3f5SEric Andersson 432c17ca3f5SEric Andersson if (bma150->client->irq) { 433c17ca3f5SEric Andersson error = bma150_set_any_motion_interrupt(bma150, 434c17ca3f5SEric Andersson cfg->any_motion_int, 435c17ca3f5SEric Andersson cfg->any_motion_dur, 436c17ca3f5SEric Andersson cfg->any_motion_thres); 437c17ca3f5SEric Andersson if (error) 438c17ca3f5SEric Andersson return error; 439c17ca3f5SEric Andersson 440c17ca3f5SEric Andersson error = bma150_set_high_g_interrupt(bma150, 441c17ca3f5SEric Andersson cfg->hg_int, cfg->hg_hyst, 442c17ca3f5SEric Andersson cfg->hg_dur, cfg->hg_thres); 443c17ca3f5SEric Andersson if (error) 444c17ca3f5SEric Andersson return error; 445c17ca3f5SEric Andersson 446c17ca3f5SEric Andersson error = bma150_set_low_g_interrupt(bma150, 447c17ca3f5SEric Andersson cfg->lg_int, cfg->lg_hyst, 448c17ca3f5SEric Andersson cfg->lg_dur, cfg->lg_thres); 449c17ca3f5SEric Andersson if (error) 450c17ca3f5SEric Andersson return error; 451c17ca3f5SEric Andersson } 452c17ca3f5SEric Andersson 453c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_SLEEP); 454c17ca3f5SEric Andersson } 455c17ca3f5SEric Andersson 4565298cc4cSBill Pemberton static void bma150_init_input_device(struct bma150_data *bma150, 457c17ca3f5SEric Andersson struct input_dev *idev) 458c17ca3f5SEric Andersson { 459c17ca3f5SEric Andersson idev->name = BMA150_DRIVER; 460c17ca3f5SEric Andersson idev->phys = BMA150_DRIVER "/input0"; 461c17ca3f5SEric Andersson idev->id.bustype = BUS_I2C; 462c17ca3f5SEric Andersson idev->dev.parent = &bma150->client->dev; 463c17ca3f5SEric Andersson 464c17ca3f5SEric Andersson idev->evbit[0] = BIT_MASK(EV_ABS); 465c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 466c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 467c17ca3f5SEric Andersson input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); 468c17ca3f5SEric Andersson } 469c17ca3f5SEric Andersson 4705298cc4cSBill Pemberton static int bma150_register_input_device(struct bma150_data *bma150) 471c17ca3f5SEric Andersson { 472c17ca3f5SEric Andersson struct input_dev *idev; 473c17ca3f5SEric Andersson int error; 474c17ca3f5SEric Andersson 475c17ca3f5SEric Andersson idev = input_allocate_device(); 476c17ca3f5SEric Andersson if (!idev) 477c17ca3f5SEric Andersson return -ENOMEM; 478c17ca3f5SEric Andersson 479c17ca3f5SEric Andersson bma150_init_input_device(bma150, idev); 480c17ca3f5SEric Andersson 481c17ca3f5SEric Andersson idev->open = bma150_irq_open; 482c17ca3f5SEric Andersson idev->close = bma150_irq_close; 483c17ca3f5SEric Andersson input_set_drvdata(idev, bma150); 484c17ca3f5SEric Andersson 485c17ca3f5SEric Andersson error = input_register_device(idev); 486c17ca3f5SEric Andersson if (error) { 487c17ca3f5SEric Andersson input_free_device(idev); 488c17ca3f5SEric Andersson return error; 489c17ca3f5SEric Andersson } 490c17ca3f5SEric Andersson 491c17ca3f5SEric Andersson bma150->input = idev; 492c17ca3f5SEric Andersson return 0; 493c17ca3f5SEric Andersson } 494c17ca3f5SEric Andersson 4955298cc4cSBill Pemberton static int bma150_register_polled_device(struct bma150_data *bma150) 496c17ca3f5SEric Andersson { 497c17ca3f5SEric Andersson struct input_polled_dev *ipoll_dev; 498c17ca3f5SEric Andersson int error; 499c17ca3f5SEric Andersson 500c17ca3f5SEric Andersson ipoll_dev = input_allocate_polled_device(); 501c17ca3f5SEric Andersson if (!ipoll_dev) 502c17ca3f5SEric Andersson return -ENOMEM; 503c17ca3f5SEric Andersson 504c17ca3f5SEric Andersson ipoll_dev->private = bma150; 505c17ca3f5SEric Andersson ipoll_dev->open = bma150_poll_open; 506c17ca3f5SEric Andersson ipoll_dev->close = bma150_poll_close; 507c17ca3f5SEric Andersson ipoll_dev->poll = bma150_poll; 508c17ca3f5SEric Andersson ipoll_dev->poll_interval = BMA150_POLL_INTERVAL; 509c17ca3f5SEric Andersson ipoll_dev->poll_interval_min = BMA150_POLL_MIN; 510c17ca3f5SEric Andersson ipoll_dev->poll_interval_max = BMA150_POLL_MAX; 511c17ca3f5SEric Andersson 512c17ca3f5SEric Andersson bma150_init_input_device(bma150, ipoll_dev->input); 513c17ca3f5SEric Andersson 514c17ca3f5SEric Andersson error = input_register_polled_device(ipoll_dev); 515c17ca3f5SEric Andersson if (error) { 516c17ca3f5SEric Andersson input_free_polled_device(ipoll_dev); 517c17ca3f5SEric Andersson return error; 518c17ca3f5SEric Andersson } 519c17ca3f5SEric Andersson 520c17ca3f5SEric Andersson bma150->input_polled = ipoll_dev; 521c17ca3f5SEric Andersson bma150->input = ipoll_dev->input; 522c17ca3f5SEric Andersson 523c17ca3f5SEric Andersson return 0; 524c17ca3f5SEric Andersson } 525c17ca3f5SEric Andersson 5265298cc4cSBill Pemberton static int bma150_probe(struct i2c_client *client, 527c17ca3f5SEric Andersson const struct i2c_device_id *id) 528c17ca3f5SEric Andersson { 529c838cb3dSJingoo Han const struct bma150_platform_data *pdata = 530c838cb3dSJingoo Han dev_get_platdata(&client->dev); 531c17ca3f5SEric Andersson const struct bma150_cfg *cfg; 532c17ca3f5SEric Andersson struct bma150_data *bma150; 533c17ca3f5SEric Andersson int chip_id; 534c17ca3f5SEric Andersson int error; 535c17ca3f5SEric Andersson 536c17ca3f5SEric Andersson if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 537c17ca3f5SEric Andersson dev_err(&client->dev, "i2c_check_functionality error\n"); 538c17ca3f5SEric Andersson return -EIO; 539c17ca3f5SEric Andersson } 540c17ca3f5SEric Andersson 541baf28d91SHans de Goede /* 542baf28d91SHans de Goede * Note if the IIO CONFIG_BMA180 driver is enabled we want to fail 543baf28d91SHans de Goede * the probe for the bma180 as the iio driver is preferred. 544baf28d91SHans de Goede */ 545c17ca3f5SEric Andersson chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); 546baf28d91SHans de Goede if (chip_id != BMA150_CHIP_ID && 547baf28d91SHans de Goede (IS_ENABLED(CONFIG_BMA180) || chip_id != BMA180_CHIP_ID)) { 548c17ca3f5SEric Andersson dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); 549c17ca3f5SEric Andersson return -EINVAL; 550c17ca3f5SEric Andersson } 551c17ca3f5SEric Andersson 552c17ca3f5SEric Andersson bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); 553c17ca3f5SEric Andersson if (!bma150) 554c17ca3f5SEric Andersson return -ENOMEM; 555c17ca3f5SEric Andersson 556c17ca3f5SEric Andersson bma150->client = client; 557c17ca3f5SEric Andersson 558c17ca3f5SEric Andersson if (pdata) { 559c17ca3f5SEric Andersson if (pdata->irq_gpio_cfg) { 560c17ca3f5SEric Andersson error = pdata->irq_gpio_cfg(); 561c17ca3f5SEric Andersson if (error) { 562c17ca3f5SEric Andersson dev_err(&client->dev, 563c17ca3f5SEric Andersson "IRQ GPIO conf. error %d, error %d\n", 564c17ca3f5SEric Andersson client->irq, error); 565c17ca3f5SEric Andersson goto err_free_mem; 566c17ca3f5SEric Andersson } 567c17ca3f5SEric Andersson } 568c17ca3f5SEric Andersson cfg = &pdata->cfg; 569c17ca3f5SEric Andersson } else { 570c17ca3f5SEric Andersson cfg = &default_cfg; 571c17ca3f5SEric Andersson } 572c17ca3f5SEric Andersson 573c17ca3f5SEric Andersson error = bma150_initialize(bma150, cfg); 574c17ca3f5SEric Andersson if (error) 575c17ca3f5SEric Andersson goto err_free_mem; 576c17ca3f5SEric Andersson 577c17ca3f5SEric Andersson if (client->irq > 0) { 578c17ca3f5SEric Andersson error = bma150_register_input_device(bma150); 579c17ca3f5SEric Andersson if (error) 580c17ca3f5SEric Andersson goto err_free_mem; 581c17ca3f5SEric Andersson 582c17ca3f5SEric Andersson error = request_threaded_irq(client->irq, 583c17ca3f5SEric Andersson NULL, bma150_irq_thread, 584c17ca3f5SEric Andersson IRQF_TRIGGER_RISING | IRQF_ONESHOT, 585c17ca3f5SEric Andersson BMA150_DRIVER, bma150); 586c17ca3f5SEric Andersson if (error) { 587c17ca3f5SEric Andersson dev_err(&client->dev, 588c17ca3f5SEric Andersson "irq request failed %d, error %d\n", 589c17ca3f5SEric Andersson client->irq, error); 590c17ca3f5SEric Andersson input_unregister_device(bma150->input); 591c17ca3f5SEric Andersson goto err_free_mem; 592c17ca3f5SEric Andersson } 593c17ca3f5SEric Andersson } else { 594c17ca3f5SEric Andersson error = bma150_register_polled_device(bma150); 595c17ca3f5SEric Andersson if (error) 596c17ca3f5SEric Andersson goto err_free_mem; 597c17ca3f5SEric Andersson } 598c17ca3f5SEric Andersson 599c17ca3f5SEric Andersson i2c_set_clientdata(client, bma150); 600c17ca3f5SEric Andersson 601c17ca3f5SEric Andersson pm_runtime_enable(&client->dev); 602c17ca3f5SEric Andersson 603c17ca3f5SEric Andersson return 0; 604c17ca3f5SEric Andersson 605c17ca3f5SEric Andersson err_free_mem: 606c17ca3f5SEric Andersson kfree(bma150); 607c17ca3f5SEric Andersson return error; 608c17ca3f5SEric Andersson } 609c17ca3f5SEric Andersson 610e2619cf7SBill Pemberton static int bma150_remove(struct i2c_client *client) 611c17ca3f5SEric Andersson { 612c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 613c17ca3f5SEric Andersson 614c17ca3f5SEric Andersson pm_runtime_disable(&client->dev); 615c17ca3f5SEric Andersson 616c17ca3f5SEric Andersson if (client->irq > 0) { 617c17ca3f5SEric Andersson free_irq(client->irq, bma150); 618c17ca3f5SEric Andersson input_unregister_device(bma150->input); 619c17ca3f5SEric Andersson } else { 620c17ca3f5SEric Andersson input_unregister_polled_device(bma150->input_polled); 621c17ca3f5SEric Andersson input_free_polled_device(bma150->input_polled); 622c17ca3f5SEric Andersson } 623c17ca3f5SEric Andersson 624c17ca3f5SEric Andersson kfree(bma150); 625c17ca3f5SEric Andersson 626c17ca3f5SEric Andersson return 0; 627c17ca3f5SEric Andersson } 628c17ca3f5SEric Andersson 629c17ca3f5SEric Andersson #ifdef CONFIG_PM 630c17ca3f5SEric Andersson static int bma150_suspend(struct device *dev) 631c17ca3f5SEric Andersson { 632c17ca3f5SEric Andersson struct i2c_client *client = to_i2c_client(dev); 633c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 634c17ca3f5SEric Andersson 635c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_SLEEP); 636c17ca3f5SEric Andersson } 637c17ca3f5SEric Andersson 638c17ca3f5SEric Andersson static int bma150_resume(struct device *dev) 639c17ca3f5SEric Andersson { 640c17ca3f5SEric Andersson struct i2c_client *client = to_i2c_client(dev); 641c17ca3f5SEric Andersson struct bma150_data *bma150 = i2c_get_clientdata(client); 642c17ca3f5SEric Andersson 643c17ca3f5SEric Andersson return bma150_set_mode(bma150, BMA150_MODE_NORMAL); 644c17ca3f5SEric Andersson } 645c17ca3f5SEric Andersson #endif 646c17ca3f5SEric Andersson 647c17ca3f5SEric Andersson static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); 648c17ca3f5SEric Andersson 649c17ca3f5SEric Andersson static const struct i2c_device_id bma150_id[] = { 650c17ca3f5SEric Andersson { "bma150", 0 }, 651baf28d91SHans de Goede #if !IS_ENABLED(CONFIG_BMA180) 652ef3714fdSDr. H. Nikolaus Schaller { "bma180", 0 }, 653baf28d91SHans de Goede #endif 654c17ca3f5SEric Andersson { "smb380", 0 }, 655c17ca3f5SEric Andersson { "bma023", 0 }, 656c17ca3f5SEric Andersson { } 657c17ca3f5SEric Andersson }; 658c17ca3f5SEric Andersson 659c17ca3f5SEric Andersson MODULE_DEVICE_TABLE(i2c, bma150_id); 660c17ca3f5SEric Andersson 661c17ca3f5SEric Andersson static struct i2c_driver bma150_driver = { 662c17ca3f5SEric Andersson .driver = { 663c17ca3f5SEric Andersson .name = BMA150_DRIVER, 664c17ca3f5SEric Andersson .pm = &bma150_pm, 665c17ca3f5SEric Andersson }, 666c17ca3f5SEric Andersson .class = I2C_CLASS_HWMON, 667c17ca3f5SEric Andersson .id_table = bma150_id, 668c17ca3f5SEric Andersson .probe = bma150_probe, 6691cb0aa88SBill Pemberton .remove = bma150_remove, 670c17ca3f5SEric Andersson }; 671c17ca3f5SEric Andersson 6721b92c1cfSAxel Lin module_i2c_driver(bma150_driver); 673c17ca3f5SEric Andersson 674c17ca3f5SEric Andersson MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>"); 675c17ca3f5SEric Andersson MODULE_DESCRIPTION("BMA150 driver"); 676c17ca3f5SEric Andersson MODULE_LICENSE("GPL"); 677