/* Date: 2011/4/8 11:00:00 * Revision: 2.5 */ /* * This software program is licensed subject to the GNU General Public License * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html * (C) Copyright 2011 Bosch Sensortec GmbH * All Rights Reserved */ /* file BMA250.c brief This file contains all function implementations for the BMA250 in linux */ #include #include #include #include #include #include #include #include #include "../init-input.h" //#include //#include #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND #include #endif #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM) #include #endif #endif enum { DEBUG_INIT = 1U << 0, DEBUG_CONTROL_INFO = 1U << 1, DEBUG_DATA_INFO = 1U << 2, DEBUG_SUSPEND = 1U << 3, }; static u32 debug_mask = 0; #define dprintk(level_mask, fmt, arg...) if (unlikely(debug_mask & level_mask)) \ printk(KERN_DEBUG fmt , ## arg) module_param_named(debug_mask, debug_mask, int, 0644); #define SENSOR_NAME "bma250" #define GRAVITY_EARTH 9806550 #define ABSMIN_2G (-GRAVITY_EARTH * 2) #define ABSMAX_2G (GRAVITY_EARTH * 2) #define SLOPE_THRESHOLD_VALUE 32 #define SLOPE_DURATION_VALUE 1 #define INTERRUPT_LATCH_MODE 13 #define INTERRUPT_ENABLE 1 #define INTERRUPT_DISABLE 0 #define MAP_SLOPE_INTERRUPT 2 #define SLOPE_X_INDEX 5 #define SLOPE_Y_INDEX 6 #define SLOPE_Z_INDEX 7 #define BMA250_MAX_DELAY 200 #define BMA150_CHIP_ID 2 #define BMA250_CHIP_ID 3 #define BMA250E_CHIP_ID 0xF9 #define BMA250_RANGE_SET 0 #define BMA250_BW_SET 4 #define BMA223_CHIP_ID 0xF8 /* * * register definitions * */ #define BMA250_CHIP_ID_REG 0x00 #define BMA250_VERSION_REG 0x01 #define BMA250_X_AXIS_LSB_REG 0x02 #define BMA250_X_AXIS_MSB_REG 0x03 #define BMA250_Y_AXIS_LSB_REG 0x04 #define BMA250_Y_AXIS_MSB_REG 0x05 #define BMA250_Z_AXIS_LSB_REG 0x06 #define BMA250_Z_AXIS_MSB_REG 0x07 #define BMA250_TEMP_RD_REG 0x08 #define BMA250_STATUS1_REG 0x09 #define BMA250_STATUS2_REG 0x0A #define BMA250_STATUS_TAP_SLOPE_REG 0x0B #define BMA250_STATUS_ORIENT_HIGH_REG 0x0C #define BMA250_RANGE_SEL_REG 0x0F #define BMA250_BW_SEL_REG 0x10 #define BMA250_MODE_CTRL_REG 0x11 #define BMA250_LOW_NOISE_CTRL_REG 0x12 #define BMA250_DATA_CTRL_REG 0x13 #define BMA250_RESET_REG 0x14 #define BMA250_INT_ENABLE1_REG 0x16 #define BMA250_INT_ENABLE2_REG 0x17 #define BMA250_INT1_PAD_SEL_REG 0x19 #define BMA250_INT_DATA_SEL_REG 0x1A #define BMA250_INT2_PAD_SEL_REG 0x1B #define BMA250_INT_SRC_REG 0x1E #define BMA250_INT_SET_REG 0x20 #define BMA250_INT_CTRL_REG 0x21 #define BMA250_LOW_DURN_REG 0x22 #define BMA250_LOW_THRES_REG 0x23 #define BMA250_LOW_HIGH_HYST_REG 0x24 #define BMA250_HIGH_DURN_REG 0x25 #define BMA250_HIGH_THRES_REG 0x26 #define BMA250_SLOPE_DURN_REG 0x27 #define BMA250_SLOPE_THRES_REG 0x28 #define BMA250_TAP_PARAM_REG 0x2A #define BMA250_TAP_THRES_REG 0x2B #define BMA250_ORIENT_PARAM_REG 0x2C #define BMA250_THETA_BLOCK_REG 0x2D #define BMA250_THETA_FLAT_REG 0x2E #define BMA250_FLAT_HOLD_TIME_REG 0x2F #define BMA250_STATUS_LOW_POWER_REG 0x31 #define BMA250_SELF_TEST_REG 0x32 #define BMA250_EEPROM_CTRL_REG 0x33 #define BMA250_SERIAL_CTRL_REG 0x34 #define BMA250_CTRL_UNLOCK_REG 0x35 #define BMA250_OFFSET_CTRL_REG 0x36 #define BMA250_OFFSET_PARAMS_REG 0x37 #define BMA250_OFFSET_FILT_X_REG 0x38 #define BMA250_OFFSET_FILT_Y_REG 0x39 #define BMA250_OFFSET_FILT_Z_REG 0x3A #define BMA250_OFFSET_UNFILT_X_REG 0x3B #define BMA250_OFFSET_UNFILT_Y_REG 0x3C #define BMA250_OFFSET_UNFILT_Z_REG 0x3D #define BMA250_SPARE_0_REG 0x3E #define BMA250_SPARE_1_REG 0x3F #define BMA250_ACC_X_LSB__POS 6 #define BMA250_ACC_X_LSB__LEN 2 #define BMA250_ACC_X_LSB__MSK 0xC0 #define BMA250_ACC_X_LSB__REG BMA250_X_AXIS_LSB_REG #define BMA250_ACC_X_MSB__POS 0 #define BMA250_ACC_X_MSB__LEN 8 #define BMA250_ACC_X_MSB__MSK 0xFF #define BMA250_ACC_X_MSB__REG BMA250_X_AXIS_MSB_REG #define BMA250_ACC_Y_LSB__POS 6 #define BMA250_ACC_Y_LSB__LEN 2 #define BMA250_ACC_Y_LSB__MSK 0xC0 #define BMA250_ACC_Y_LSB__REG BMA250_Y_AXIS_LSB_REG #define BMA250_ACC_Y_MSB__POS 0 #define BMA250_ACC_Y_MSB__LEN 8 #define BMA250_ACC_Y_MSB__MSK 0xFF #define BMA250_ACC_Y_MSB__REG BMA250_Y_AXIS_MSB_REG #define BMA250_ACC_Z_LSB__POS 6 #define BMA250_ACC_Z_LSB__LEN 2 #define BMA250_ACC_Z_LSB__MSK 0xC0 #define BMA250_ACC_Z_LSB__REG BMA250_Z_AXIS_LSB_REG #define BMA250_ACC_Z_MSB__POS 0 #define BMA250_ACC_Z_MSB__LEN 8 #define BMA250_ACC_Z_MSB__MSK 0xFF #define BMA250_ACC_Z_MSB__REG BMA250_Z_AXIS_MSB_REG #define BMA250_RANGE_SEL__POS 0 #define BMA250_RANGE_SEL__LEN 4 #define BMA250_RANGE_SEL__MSK 0x0F #define BMA250_RANGE_SEL__REG BMA250_RANGE_SEL_REG #define BMA250_BANDWIDTH__POS 0 #define BMA250_BANDWIDTH__LEN 5 #define BMA250_BANDWIDTH__MSK 0x1F #define BMA250_BANDWIDTH__REG BMA250_BW_SEL_REG #define BMA250_EN_D_SUSPEND__POS 5 #define BMA250_EN_D_SUSPEND__LEN 1 #define BMA250_EN_D_SUSPEND__MSK 0x20 #define BMA250_EN_D_SUSPEND__REG BMA250_MODE_CTRL_REG #define BMA250_EN_LOW_POWER__POS 6 #define BMA250_EN_LOW_POWER__LEN 1 #define BMA250_EN_LOW_POWER__MSK 0x40 #define BMA250_EN_LOW_POWER__REG BMA250_MODE_CTRL_REG #define BMA250_EN_SUSPEND__POS 7 #define BMA250_EN_SUSPEND__LEN 1 #define BMA250_EN_SUSPEND__MSK 0x80 #define BMA250_EN_SUSPEND__REG BMA250_MODE_CTRL_REG #define BMA250_GET_BITSLICE(regvar, bitname)\ ((regvar & bitname##__MSK) >> bitname##__POS) #define BMA250_SET_BITSLICE(regvar, bitname, val)\ ((regvar & ~bitname##__MSK) | ((val<adapter; int ret; dprintk(DEBUG_INIT, "%s enter \n", __func__); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; if (twi_id == adapter->nr) { for (i2c_num = 0; i2c_num < (sizeof(i2c_address)/sizeof(i2c_address[0]));i2c_num++) { client->addr = i2c_address[i2c_num]; pr_info("%s:addr= 0x%x,i2c_num:%d\n",__func__,client->addr,i2c_num); ret = i2c_smbus_read_byte_data(client,BMA250_CHIP_ID_REG); pr_info("Read ID value is :%d",ret); if ((ret &0x00FF) == BMA250_CHIP_ID) { pr_info("Bosch Sensortec Device detected!\n" ); strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE); return 0; } else if((ret &0x00FF) == BMA150_CHIP_ID) { pr_info("Bosch Sensortec Device detected!\n" \ "BMA150 registered I2C driver!\n"); strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE); return 0; } else if((ret &0x00FF) == BMA250E_CHIP_ID) { pr_info("Bosch Sensortec Device detected!\n" \ "BMA250E registered I2C driver!\n"); strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE); deep_suspend = 1; return 0; } else if((ret &0x00FF) == BMA223_CHIP_ID) { pr_info("Bosch Sensortec Device detected!\n" \ "BMA223 registered I2C driver!\n"); strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE); deep_suspend = 1; return 0; } } pr_info("%s:Bosch Sensortec Device not found, \ maybe the other gsensor equipment! \n",__func__); return -ENODEV; } else { return -ENODEV; } } static int bma250_smbus_read_byte(struct i2c_client *client, unsigned char reg_addr, unsigned char *data) { s32 dummy; dummy = i2c_smbus_read_byte_data(client, reg_addr); if (dummy < 0) return -1; *data = dummy & 0x000000ff; return 0; } static int bma250_smbus_write_byte(struct i2c_client *client, unsigned char reg_addr, unsigned char *data) { s32 dummy; dummy = i2c_smbus_write_byte_data(client, reg_addr, *data); if (dummy < 0) return -1; return 0; } static int bma250_smbus_read_byte_block(struct i2c_client *client, unsigned char reg_addr, unsigned char *data, unsigned char len) { s32 dummy; dummy = i2c_smbus_read_i2c_block_data(client, reg_addr, len, data); if (dummy < 0) return -1; return 0; } static int bma250_set_mode(struct i2c_client *client, unsigned char Mode) { int comres = 0; unsigned char data1 = '\0'; if (client == NULL) { comres = -1; } else{ if (Mode < 4) { comres = bma250_smbus_read_byte(client, BMA250_EN_LOW_POWER__REG, &data1); switch (Mode) { case BMA250_MODE_NORMAL: data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_LOW_POWER, 0); data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_SUSPEND, 0); if(deep_suspend) data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_D_SUSPEND, 0); break; case BMA250_MODE_LOWPOWER: data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_LOW_POWER, 1); data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_SUSPEND, 0); if(deep_suspend) data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_D_SUSPEND, 0); break; case BMA250_MODE_SUSPEND: data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_LOW_POWER, 0); data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_SUSPEND, 1); if(deep_suspend) data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_D_SUSPEND, 0); break; case BMA250_MODE_D_SUSPEND: data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_LOW_POWER, 0); data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_SUSPEND, 0); data1 = BMA250_SET_BITSLICE(data1, BMA250_EN_D_SUSPEND, 1); break; default: break; } comres += bma250_smbus_write_byte(client, BMA250_EN_LOW_POWER__REG, &data1); } else{ comres = -1; } } return comres; } static int bma250_get_mode(struct i2c_client *client, unsigned char *Mode) { int comres = 0; if (client == NULL) { comres = -1; } else{ comres = bma250_smbus_read_byte(client, BMA250_EN_LOW_POWER__REG, Mode); *Mode = (*Mode) >> 6; } return comres; } static int bma250_set_range(struct i2c_client *client, unsigned char Range) { int comres = 0; unsigned char data1 = '\0'; if (client == NULL) { comres = -1; } else{ if (Range < 4) { comres = bma250_smbus_read_byte(client, BMA250_RANGE_SEL_REG, &data1); switch (Range) { case 0: data1 = BMA250_SET_BITSLICE(data1, BMA250_RANGE_SEL, 0); break; case 1: data1 = BMA250_SET_BITSLICE(data1, BMA250_RANGE_SEL, 5); break; case 2: data1 = BMA250_SET_BITSLICE(data1, BMA250_RANGE_SEL, 8); break; case 3: data1 = BMA250_SET_BITSLICE(data1, BMA250_RANGE_SEL, 12); break; default: break; } comres += bma250_smbus_write_byte(client, BMA250_RANGE_SEL_REG, &data1); } else{ comres = -1; } } return comres; } static int bma250_get_range(struct i2c_client *client, unsigned char *Range) { int comres = 0; unsigned char data = '\0'; if (client == NULL) { comres = -1; } else{ comres = bma250_smbus_read_byte(client, BMA250_RANGE_SEL__REG, &data); data = BMA250_GET_BITSLICE(data, BMA250_RANGE_SEL); *Range = data; } return comres; } static int bma250_set_bandwidth(struct i2c_client *client, unsigned char BW) { int comres = 0; unsigned char data = '\0'; int Bandwidth = 0; if (client == NULL) { comres = -1; } else{ if (BW < 8) { switch (BW) { case 0: Bandwidth = BMA250_BW_7_81HZ; break; case 1: Bandwidth = BMA250_BW_15_63HZ; break; case 2: Bandwidth = BMA250_BW_31_25HZ; break; case 3: Bandwidth = BMA250_BW_62_50HZ; break; case 4: Bandwidth = BMA250_BW_125HZ; break; case 5: Bandwidth = BMA250_BW_250HZ; break; case 6: Bandwidth = BMA250_BW_500HZ; break; case 7: Bandwidth = BMA250_BW_1000HZ; break; default: break; } comres = bma250_smbus_read_byte(client, BMA250_BANDWIDTH__REG, &data); data = BMA250_SET_BITSLICE(data, BMA250_BANDWIDTH, Bandwidth); comres += bma250_smbus_write_byte(client, BMA250_BANDWIDTH__REG, &data); } else{ comres = -1; } } return comres; } static int bma250_get_bandwidth(struct i2c_client *client, unsigned char *BW) { int comres = 0; unsigned char data = '\0'; if (client == NULL) { comres = -1; } else{ comres = bma250_smbus_read_byte(client, BMA250_BANDWIDTH__REG, &data); data = BMA250_GET_BITSLICE(data, BMA250_BANDWIDTH); if (data <= 8) { *BW = 0; } else{ if (data >= 0x0F) *BW = 7; else *BW = data - 8; } } return comres; } static int bma250_read_accel_xyz(struct i2c_client *client, struct bma250acc *acc) { int comres; unsigned char data[6] = {0}; if (client == NULL) { comres = -1; } else{ comres = bma250_smbus_read_byte_block(client, BMA250_ACC_X_LSB__REG, data, 6); acc->x = BMA250_GET_BITSLICE(data[0], BMA250_ACC_X_LSB) |(BMA250_GET_BITSLICE(data[1], BMA250_ACC_X_MSB)<x = acc->x << (sizeof(short)*8-(BMA250_ACC_X_LSB__LEN + BMA250_ACC_X_MSB__LEN)); acc->x = acc->x >> (sizeof(short)*8-(BMA250_ACC_X_LSB__LEN + BMA250_ACC_X_MSB__LEN)); acc->y = BMA250_GET_BITSLICE(data[2], BMA250_ACC_Y_LSB) | (BMA250_GET_BITSLICE(data[3], BMA250_ACC_Y_MSB)<y = acc->y << (sizeof(short)*8-(BMA250_ACC_Y_LSB__LEN + BMA250_ACC_Y_MSB__LEN)); acc->y = acc->y >> (sizeof(short)*8-(BMA250_ACC_Y_LSB__LEN + BMA250_ACC_Y_MSB__LEN)); acc->z = BMA250_GET_BITSLICE(data[4], BMA250_ACC_Z_LSB) | (BMA250_GET_BITSLICE(data[5], BMA250_ACC_Z_MSB)<z = acc->z << (sizeof(short)*8-(BMA250_ACC_Z_LSB__LEN + BMA250_ACC_Z_MSB__LEN)); acc->z = acc->z >> (sizeof(short)*8-(BMA250_ACC_Z_LSB__LEN + BMA250_ACC_Z_MSB__LEN)); } return comres; } static void bma250_work_func(struct work_struct *work) { struct bma250_data *bma250 = container_of((struct delayed_work *)work, struct bma250_data, work); static struct bma250acc acc; unsigned long delay = msecs_to_jiffies(atomic_read(&bma250->delay)); bma250_read_accel_xyz(bma250->bma250_client, &acc); input_report_abs(bma250->input, ABS_X, acc.x); input_report_abs(bma250->input, ABS_Y, acc.y); input_report_abs(bma250->input, ABS_Z, acc.z); dprintk(DEBUG_DATA_INFO, "acc.x %d, acc.y %d, acc.z %d\n", acc.x, acc.y, acc.z); input_sync(bma250->input); mutex_lock(&bma250->value_mutex); bma250->value = acc; mutex_unlock(&bma250->value_mutex); schedule_delayed_work(&bma250->work, delay); } static ssize_t bma250_range_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned char data; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); if (bma250_get_range(bma250->bma250_client, &data) < 0) return sprintf(buf, "Read error\n"); dprintk(DEBUG_CONTROL_INFO, "%d, %s\n", data, __FUNCTION__); return sprintf(buf, "%d\n", data); } static ssize_t bma250_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); error = strict_strtoul(buf, 10, &data); if (error) return error; if (bma250_set_range(bma250->bma250_client, (unsigned char) data) < 0) return -EINVAL; return count; } static ssize_t bma250_bandwidth_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned char data; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); if (bma250_get_bandwidth(bma250->bma250_client, &data) < 0) return sprintf(buf, "Read error\n"); dprintk(DEBUG_CONTROL_INFO, "%d, %s\n", data, __FUNCTION__); return sprintf(buf, "%d\n", data); } static ssize_t bma250_bandwidth_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); error = strict_strtoul(buf, 10, &data); if (error) return error; if (bma250_set_bandwidth(bma250->bma250_client, (unsigned char) data) < 0) return -EINVAL; return count; } static ssize_t bma250_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned char data; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); if (bma250_get_mode(bma250->bma250_client, &data) < 0) return sprintf(buf, "Read error\n"); dprintk(DEBUG_CONTROL_INFO, "%d, %s\n", data, __FUNCTION__); return sprintf(buf, "%d\n", data); } static ssize_t bma250_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); error = strict_strtoul(buf, 10, &data); if (error) return error; if (bma250_set_mode(bma250->bma250_client, (unsigned char) data) < 0) return -EINVAL; return count; } static ssize_t bma250_value_show(struct device *dev, struct device_attribute *attr, char *buf) { struct input_dev *input = to_input_dev(dev); struct bma250_data *bma250 = input_get_drvdata(input); struct bma250acc acc_value; mutex_lock(&bma250->value_mutex); acc_value = bma250->value; mutex_unlock(&bma250->value_mutex); dprintk(DEBUG_CONTROL_INFO, "x=%d, y=%d, z=%d ,%s\n", acc_value.x, acc_value.y, acc_value.z, __FUNCTION__); return sprintf(buf, "%d %d %d\n", acc_value.x, acc_value.y, acc_value.z); } static ssize_t bma250_delay_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); dprintk(DEBUG_CONTROL_INFO, "%d, %s\n", atomic_read(&bma250->delay), __FUNCTION__); return sprintf(buf, "%d\n", atomic_read(&bma250->delay)); } static ssize_t bma250_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); error = strict_strtoul(buf, 10, &data); if (error) return error; if (data > BMA250_MAX_DELAY) data = BMA250_MAX_DELAY; atomic_set(&bma250->delay, (unsigned int) data); return count; } static ssize_t bma250_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); dprintk(DEBUG_CONTROL_INFO, "%d, %s\n", atomic_read(&bma250->enable), __FUNCTION__); return sprintf(buf, "%d\n", atomic_read(&bma250->enable)); } static void bma250_set_enable(struct device *dev, int enable) { struct i2c_client *client = to_i2c_client(dev); struct bma250_data *bma250 = i2c_get_clientdata(client); int pre_enable = atomic_read(&bma250->enable); mutex_lock(&bma250->enable_mutex); if (enable) { if (pre_enable ==0) { bma250_set_mode(bma250->bma250_client, BMA250_MODE_NORMAL); schedule_delayed_work(&bma250->work, msecs_to_jiffies(atomic_read(&bma250->delay))); atomic_set(&bma250->enable, 1); } } else { if (pre_enable ==1) { if(deep_suspend) bma250_set_mode(bma250->bma250_client, BMA250_MODE_D_SUSPEND); else bma250_set_mode(bma250->bma250_client, BMA250_MODE_SUSPEND); cancel_delayed_work_sync(&bma250->work); atomic_set(&bma250->enable, 0); } } mutex_unlock(&bma250->enable_mutex); } static ssize_t bma250_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; error = strict_strtoul(buf, 10, &data); if (error) return error; if ((data == 0)||(data==1)) { bma250_set_enable(dev,data); } return count; } static DEVICE_ATTR(range, S_IRUGO|S_IWUSR|S_IWGRP, bma250_range_show, bma250_range_store); static DEVICE_ATTR(bandwidth, S_IRUGO|S_IWUSR|S_IWGRP, bma250_bandwidth_show, bma250_bandwidth_store); static DEVICE_ATTR(mode, S_IRUGO|S_IWUSR|S_IWGRP, bma250_mode_show, bma250_mode_store); static DEVICE_ATTR(value, S_IRUGO, bma250_value_show, NULL); static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR|S_IWGRP, bma250_delay_show, bma250_delay_store); static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP, bma250_enable_show, bma250_enable_store); static struct attribute *bma250_attributes[] = { &dev_attr_range.attr, &dev_attr_bandwidth.attr, &dev_attr_mode.attr, &dev_attr_value.attr, &dev_attr_delay.attr, &dev_attr_enable.attr, NULL }; static struct attribute_group bma250_attribute_group = { .attrs = bma250_attributes }; static int bma250_input_init(struct bma250_data *bma250) { struct input_dev *dev; int err; dev = input_allocate_device(); if (!dev) return -ENOMEM; dev->name = SENSOR_NAME; dev->id.bustype = BUS_I2C; input_set_capability(dev, EV_ABS, ABS_MISC); input_set_abs_params(dev, ABS_X, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_abs_params(dev, ABS_Y, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_abs_params(dev, ABS_Z, ABSMIN_2G, ABSMAX_2G, 0, 0); input_set_drvdata(dev, bma250); err = input_register_device(dev); if (err < 0) { input_free_device(dev); return err; } bma250->input = dev; return 0; } static void bma250_input_delete(struct bma250_data *bma250) { struct input_dev *dev = bma250->input; input_unregister_device(dev); } static int bma250_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; struct bma250_data *data; dprintk(DEBUG_INIT, "bma250: probe\n"); dprintk(DEBUG_INIT, "bma250 probe i2c address is %d \n",i2c_address[i2c_num]); client->addr =i2c_address[i2c_num]; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { printk(KERN_INFO "i2c_check_functionality error\n"); goto exit; } data = kzalloc(sizeof(struct bma250_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } i2c_set_clientdata(client, data); data->bma250_client = client; mutex_init(&data->value_mutex); mutex_init(&data->mode_mutex); mutex_init(&data->enable_mutex); bma250_set_bandwidth(client, BMA250_BW_SET); bma250_set_range(client, BMA250_RANGE_SET); INIT_DELAYED_WORK(&data->work, bma250_work_func); dprintk(DEBUG_INIT, "bma: INIT_DELAYED_WORK\n"); atomic_set(&data->delay, BMA250_MAX_DELAY); atomic_set(&data->enable, 0); err = bma250_input_init(data); if (err < 0) { printk("bma: bma250_input_init err\n"); goto kfree_exit; } err = sysfs_create_group(&data->input->dev.kobj, &bma250_attribute_group); if (err < 0) { printk("bma: sysfs_create_group err\n"); goto error_sysfs; } #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; data->early_suspend.suspend = bma250_early_suspend; data->early_suspend.resume = bma250_late_resume; register_early_suspend(&data->early_suspend); #endif #endif dprintk(DEBUG_INIT, "bma250: probe end\n"); return 0; error_sysfs: printk("%s error_sysfs\n",__FUNCTION__); bma250_input_delete(data); kfree_exit: printk("%s kfree_exit\n",__FUNCTION__); kfree(data); exit: printk("%s exit\n",__FUNCTION__); return err; } #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND static void bma250_early_suspend(struct early_suspend *h) { struct bma250_data *data = container_of(h, struct bma250_data, early_suspend); dprintk(DEBUG_SUSPEND, "bma250: early suspend\n"); if (NORMAL_STANDBY == standby_type) { mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_SUSPEND); cancel_delayed_work_sync(&data->work); } mutex_unlock(&data->enable_mutex); } else if (SUPER_STANDBY == standby_type) { if (bma250_get_bandwidth(data->bma250_client, &data->bandwidth_state) < 0) printk("suspend: read bandwidth err\n"); if (bma250_get_range(data->bma250_client, &data->range_state) < 0) printk("suspend: read range err\n"); mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_SUSPEND); cancel_delayed_work_sync(&data->work); } mutex_unlock(&data->enable_mutex); } } static void bma250_late_resume(struct early_suspend *h) { struct bma250_data *data = i2c_get_clientdata(client); dprintk(DEBUG_SUSPEND, "bma250: resume\n"); if (NORMAL_STANDBY == standby_type) { mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_NORMAL); schedule_delayed_work(&data->work, msecs_to_jiffies(atomic_read(&data->delay))); } mutex_unlock(&data->enable_mutex); } else if (SUPER_STANDBY == standby_type) { if (bma250_set_bandwidth(data->bma250_client, data->bandwidth_state) < 0) printk("suspend: write bandwidth err\n"); if (bma250_set_range(data->bma250_client, data->range_state) < 0) printk("suspend: write range err\n"); mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_NORMAL); schedule_delayed_work(&data->work, msecs_to_jiffies(atomic_read(&data->delay))); } mutex_unlock(&data->enable_mutex); } } #else #ifdef CONFIG_PM static int bma250_resume(struct i2c_client *client) { struct bma250_data *data = i2c_get_clientdata(client); dprintk(DEBUG_SUSPEND, "bma250: resume\n"); if (NORMAL_STANDBY == standby_type) { mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_NORMAL); schedule_delayed_work(&data->work, msecs_to_jiffies(atomic_read(&data->delay))); } mutex_unlock(&data->enable_mutex); } else if (SUPER_STANDBY == standby_type) { if (bma250_set_bandwidth(data->bma250_client, data->bandwidth_state) < 0) printk("suspend: write bandwidth err\n"); if (bma250_set_range(data->bma250_client, data->range_state) < 0) printk("suspend: write range err\n"); mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_NORMAL); schedule_delayed_work(&data->work, msecs_to_jiffies(atomic_read(&data->delay))); } mutex_unlock(&data->enable_mutex); } return 0; } static int bma250_suspend(struct i2c_client *client, pm_message_t mesg) { struct bma250_data *data = i2c_get_clientdata(client); dprintk(DEBUG_SUSPEND, "bma250: suspend\n"); if (NORMAL_STANDBY == standby_type) { mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_SUSPEND); cancel_delayed_work_sync(&data->work); } mutex_unlock(&data->enable_mutex); } else if (SUPER_STANDBY == standby_type) { if (bma250_get_bandwidth(data->bma250_client, &data->bandwidth_state) < 0) printk("suspend: read bandwidth err\n"); if (bma250_get_range(data->bma250_client, &data->range_state) < 0) printk("suspend: read range err\n"); mutex_lock(&data->enable_mutex); if (atomic_read(&data->enable)==1) { bma250_set_mode(data->bma250_client, BMA250_MODE_SUSPEND); cancel_delayed_work_sync(&data->work); } mutex_unlock(&data->enable_mutex); } return 0; } #endif #endif /* CONFIG_HAS_EARLYSUSPEND */ #endif static int bma250_remove(struct i2c_client *client) { struct bma250_data *data = i2c_get_clientdata(client); bma250_set_enable(&client->dev, 0); #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&data->early_suspend); #endif #endif sysfs_remove_group(&data->input->dev.kobj, &bma250_attribute_group); bma250_input_delete(data); i2c_set_clientdata(client, NULL); kfree(data); return 0; } static const struct i2c_device_id bma250_id[] = { { SENSOR_NAME, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, bma250_id); static const struct of_device_id bma250_of_match[] = { {.compatible = "bosch,bma250"}, {}, }; MODULE_DEVICE_TABLE(of, bma250_of_match); static struct i2c_driver bma250_driver = { .class = I2C_CLASS_HWMON, .driver = { .owner = THIS_MODULE, .name = SENSOR_NAME, .of_match_table = bma250_of_match, }, .id_table = bma250_id, .probe = bma250_probe, .remove = bma250_remove, #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND #else #ifdef CONFIG_PM .suspend = bma250_suspend, .resume = bma250_resume, #endif #endif #endif .detect = gsensor_detect, .address_list = normal_i2c, }; static int __init BMA250_init(void) { int ret = -1; dprintk(DEBUG_INIT, "bma250: init\n"); if (input_fetch_sysconfig_para(&(gsensor_info.input_type))) { printk("%s: err.\n", __func__); return -1; } else{ ret = input_init_platform_resource(&(gsensor_info.input_type)); if (0 != ret){ printk("%s:ctp_ops.init_platform_resource err. \n", __func__); } } twi_id = gsensor_info.twi_id; dprintk(DEBUG_INIT, "%s i2c twi is %d \n", __func__, twi_id); input_set_power_enable(&(gsensor_info.input_type),1); ret = i2c_add_driver(&bma250_driver); return ret; } static void __exit BMA250_exit(void) { dprintk(DEBUG_INIT, "bma250:exit\n"); i2c_del_driver(&bma250_driver); input_set_power_enable(&(gsensor_info.input_type),0); } MODULE_AUTHOR("Albert Zhang "); MODULE_DESCRIPTION("BMA250 driver"); MODULE_LICENSE("GPL"); module_init(BMA250_init); module_exit(BMA250_exit);