| /* Date: 2011/3/7 11:00:00 |
| * Revision: 2.11 |
| */ |
| |
| /* |
| * 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 BMA150.c |
| brief This file contains all function implementations for the BMA150 in linux |
| |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/init.h> |
| #include <linux/i2c.h> |
| #include <linux/interrupt.h> |
| #include <linux/input.h> |
| #include <linux/workqueue.h> |
| #include <linux/slab.h> |
| #include <linux/mutex.h> |
| #include <linux/bma150.h> |
| |
| #define SENSOR_NAME "bma150" |
| #define GRAVITY_EARTH 9806550 |
| #define ABSMIN_2G (-GRAVITY_EARTH * 2) |
| #define ABSMAX_2G (GRAVITY_EARTH * 2) |
| #define BMA150_MAX_DELAY 200 |
| #define BMA150_CHIP_ID 2 |
| #define BMA150_RANGE_SET 0 |
| #define BMA150_BW_SET 4 |
| |
| |
| |
| #define BMA150_CHIP_ID_REG 0x00 |
| #define BMA150_X_AXIS_LSB_REG 0x02 |
| #define BMA150_X_AXIS_MSB_REG 0x03 |
| #define BMA150_Y_AXIS_LSB_REG 0x04 |
| #define BMA150_Y_AXIS_MSB_REG 0x05 |
| #define BMA150_Z_AXIS_LSB_REG 0x06 |
| #define BMA150_Z_AXIS_MSB_REG 0x07 |
| #define BMA150_STATUS_REG 0x09 |
| #define BMA150_CTRL_REG 0x0a |
| #define BMA150_CONF1_REG 0x0b |
| |
| #define BMA150_CUSTOMER1_REG 0x12 |
| #define BMA150_CUSTOMER2_REG 0x13 |
| #define BMA150_RANGE_BWIDTH_REG 0x14 |
| #define BMA150_CONF2_REG 0x15 |
| |
| #define BMA150_OFFS_GAIN_X_REG 0x16 |
| #define BMA150_OFFS_GAIN_Y_REG 0x17 |
| #define BMA150_OFFS_GAIN_Z_REG 0x18 |
| #define BMA150_OFFS_GAIN_T_REG 0x19 |
| #define BMA150_OFFSET_X_REG 0x1a |
| #define BMA150_OFFSET_Y_REG 0x1b |
| #define BMA150_OFFSET_Z_REG 0x1c |
| #define BMA150_OFFSET_T_REG 0x1d |
| |
| #define BMA150_CHIP_ID__POS 0 |
| #define BMA150_CHIP_ID__MSK 0x07 |
| #define BMA150_CHIP_ID__LEN 3 |
| #define BMA150_CHIP_ID__REG BMA150_CHIP_ID_REG |
| |
| /* DATA REGISTERS */ |
| |
| #define BMA150_NEW_DATA_X__POS 0 |
| #define BMA150_NEW_DATA_X__LEN 1 |
| #define BMA150_NEW_DATA_X__MSK 0x01 |
| #define BMA150_NEW_DATA_X__REG BMA150_X_AXIS_LSB_REG |
| |
| #define BMA150_ACC_X_LSB__POS 6 |
| #define BMA150_ACC_X_LSB__LEN 2 |
| #define BMA150_ACC_X_LSB__MSK 0xC0 |
| #define BMA150_ACC_X_LSB__REG BMA150_X_AXIS_LSB_REG |
| |
| #define BMA150_ACC_X_MSB__POS 0 |
| #define BMA150_ACC_X_MSB__LEN 8 |
| #define BMA150_ACC_X_MSB__MSK 0xFF |
| #define BMA150_ACC_X_MSB__REG BMA150_X_AXIS_MSB_REG |
| |
| #define BMA150_ACC_Y_LSB__POS 6 |
| #define BMA150_ACC_Y_LSB__LEN 2 |
| #define BMA150_ACC_Y_LSB__MSK 0xC0 |
| #define BMA150_ACC_Y_LSB__REG BMA150_Y_AXIS_LSB_REG |
| |
| #define BMA150_ACC_Y_MSB__POS 0 |
| #define BMA150_ACC_Y_MSB__LEN 8 |
| #define BMA150_ACC_Y_MSB__MSK 0xFF |
| #define BMA150_ACC_Y_MSB__REG BMA150_Y_AXIS_MSB_REG |
| |
| #define BMA150_ACC_Z_LSB__POS 6 |
| #define BMA150_ACC_Z_LSB__LEN 2 |
| #define BMA150_ACC_Z_LSB__MSK 0xC0 |
| #define BMA150_ACC_Z_LSB__REG BMA150_Z_AXIS_LSB_REG |
| |
| #define BMA150_ACC_Z_MSB__POS 0 |
| #define BMA150_ACC_Z_MSB__LEN 8 |
| #define BMA150_ACC_Z_MSB__MSK 0xFF |
| #define BMA150_ACC_Z_MSB__REG BMA150_Z_AXIS_MSB_REG |
| |
| /* CONTROL BITS */ |
| |
| #define BMA150_SLEEP__POS 0 |
| #define BMA150_SLEEP__LEN 1 |
| #define BMA150_SLEEP__MSK 0x01 |
| #define BMA150_SLEEP__REG BMA150_CTRL_REG |
| |
| #define BMA150_SOFT_RESET__POS 1 |
| #define BMA150_SOFT_RESET__LEN 1 |
| #define BMA150_SOFT_RESET__MSK 0x02 |
| #define BMA150_SOFT_RESET__REG BMA150_CTRL_REG |
| |
| #define BMA150_EE_W__POS 4 |
| #define BMA150_EE_W__LEN 1 |
| #define BMA150_EE_W__MSK 0x10 |
| #define BMA150_EE_W__REG BMA150_CTRL_REG |
| |
| #define BMA150_UPDATE_IMAGE__POS 5 |
| #define BMA150_UPDATE_IMAGE__LEN 1 |
| #define BMA150_UPDATE_IMAGE__MSK 0x20 |
| #define BMA150_UPDATE_IMAGE__REG BMA150_CTRL_REG |
| |
| #define BMA150_RESET_INT__POS 6 |
| #define BMA150_RESET_INT__LEN 1 |
| #define BMA150_RESET_INT__MSK 0x40 |
| #define BMA150_RESET_INT__REG BMA150_CTRL_REG |
| |
| /* BANDWIDTH dependend definitions */ |
| |
| #define BMA150_BANDWIDTH__POS 0 |
| #define BMA150_BANDWIDTH__LEN 3 |
| #define BMA150_BANDWIDTH__MSK 0x07 |
| #define BMA150_BANDWIDTH__REG BMA150_RANGE_BWIDTH_REG |
| |
| /* RANGE */ |
| |
| #define BMA150_RANGE__POS 3 |
| #define BMA150_RANGE__LEN 2 |
| #define BMA150_RANGE__MSK 0x18 |
| #define BMA150_RANGE__REG BMA150_RANGE_BWIDTH_REG |
| |
| /* WAKE UP */ |
| |
| #define BMA150_WAKE_UP__POS 0 |
| #define BMA150_WAKE_UP__LEN 1 |
| #define BMA150_WAKE_UP__MSK 0x01 |
| #define BMA150_WAKE_UP__REG BMA150_CONF2_REG |
| |
| #define BMA150_WAKE_UP_PAUSE__POS 1 |
| #define BMA150_WAKE_UP_PAUSE__LEN 2 |
| #define BMA150_WAKE_UP_PAUSE__MSK 0x06 |
| #define BMA150_WAKE_UP_PAUSE__REG BMA150_CONF2_REG |
| |
| #define BMA150_GET_BITSLICE(regvar, bitname)\ |
| ((regvar & bitname##__MSK) >> bitname##__POS) |
| |
| |
| #define BMA150_SET_BITSLICE(regvar, bitname, val)\ |
| ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK)) |
| |
| /* range and bandwidth */ |
| |
| #define BMA150_RANGE_2G 0 |
| #define BMA150_RANGE_4G 1 |
| #define BMA150_RANGE_8G 2 |
| |
| #define BMA150_BW_25HZ 0 |
| #define BMA150_BW_50HZ 1 |
| #define BMA150_BW_100HZ 2 |
| #define BMA150_BW_190HZ 3 |
| #define BMA150_BW_375HZ 4 |
| #define BMA150_BW_750HZ 5 |
| #define BMA150_BW_1500HZ 6 |
| |
| /* mode settings */ |
| |
| #define BMA150_MODE_NORMAL 0 |
| #define BMA150_MODE_SLEEP 2 |
| #define BMA150_MODE_WAKE_UP 3 |
| |
| struct bma150acc{ |
| s16 x, |
| y, |
| z; |
| } ; |
| |
| struct bma150_data { |
| struct i2c_client *bma150_client; |
| struct bma150_platform_data *platform_data; |
| int IRQ; |
| atomic_t delay; |
| unsigned char mode; |
| struct input_dev *input; |
| struct bma150acc value; |
| struct mutex value_mutex; |
| struct mutex mode_mutex; |
| struct delayed_work work; |
| struct work_struct irq_work; |
| }; |
| |
| static int bma150_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 -EPERM; |
| *data = dummy & 0x000000ff; |
| |
| return 0; |
| } |
| |
| static int bma150_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 -EPERM; |
| return 0; |
| } |
| |
| static int bma150_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 -EPERM; |
| return 0; |
| } |
| |
| static int bma150_set_mode(struct i2c_client *client, unsigned char Mode) |
| { |
| int comres = 0; |
| unsigned char data1 = 0, data2 = 0; |
| struct bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| if (Mode < 4 && Mode != 1) { |
| |
| comres = bma150_smbus_read_byte(client, |
| BMA150_WAKE_UP__REG, &data1); |
| data1 = BMA150_SET_BITSLICE(data1, |
| BMA150_WAKE_UP, Mode); |
| comres += bma150_smbus_read_byte(client, |
| BMA150_SLEEP__REG, &data2); |
| data2 = BMA150_SET_BITSLICE(data2, |
| BMA150_SLEEP, (Mode>>1)); |
| comres += bma150_smbus_write_byte(client, |
| BMA150_WAKE_UP__REG, &data1); |
| comres += bma150_smbus_write_byte(client, |
| BMA150_SLEEP__REG, &data2); |
| mutex_lock(&bma150->mode_mutex); |
| bma150->mode = (unsigned char) Mode; |
| mutex_unlock(&bma150->mode_mutex); |
| |
| } else{ |
| comres = -1; |
| } |
| } |
| |
| return comres; |
| } |
| |
| |
| static int bma150_set_range(struct i2c_client *client, unsigned char Range) |
| { |
| int comres = 0; |
| unsigned char data = 0; |
| |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| if (Range < 3) { |
| |
| comres = bma150_smbus_read_byte(client, |
| BMA150_RANGE__REG, &data); |
| data = BMA150_SET_BITSLICE(data, BMA150_RANGE, Range); |
| comres += bma150_smbus_write_byte(client, |
| BMA150_RANGE__REG, &data); |
| |
| } else{ |
| comres = -1; |
| } |
| } |
| |
| return comres; |
| } |
| |
| static int bma150_get_range(struct i2c_client *client, unsigned char *Range) |
| { |
| int comres = 0; |
| unsigned char data; |
| |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| comres = bma150_smbus_read_byte(client, |
| BMA150_RANGE__REG, &data); |
| |
| *Range = BMA150_GET_BITSLICE(data, BMA150_RANGE); |
| |
| } |
| |
| return comres; |
| } |
| |
| |
| |
| static int bma150_set_bandwidth(struct i2c_client *client, unsigned char BW) |
| { |
| int comres = 0; |
| unsigned char data = 0; |
| |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| if (BW < 8) { |
| comres = bma150_smbus_read_byte(client, |
| BMA150_BANDWIDTH__REG, &data); |
| data = BMA150_SET_BITSLICE(data, BMA150_BANDWIDTH, BW); |
| comres += bma150_smbus_write_byte(client, |
| BMA150_BANDWIDTH__REG, &data); |
| |
| } else{ |
| comres = -1; |
| } |
| } |
| |
| return comres; |
| } |
| |
| static int bma150_get_bandwidth(struct i2c_client *client, unsigned char *BW) |
| { |
| int comres = 0; |
| unsigned char data; |
| |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| |
| |
| comres = bma150_smbus_read_byte(client, |
| BMA150_BANDWIDTH__REG, &data); |
| |
| *BW = BMA150_GET_BITSLICE(data, BMA150_BANDWIDTH); |
| |
| |
| } |
| |
| return comres; |
| } |
| |
| static int bma150_read_accel_xyz(struct i2c_client *client, |
| struct bma150acc *acc) |
| { |
| int comres; |
| unsigned char data[6]; |
| if (client == NULL) { |
| comres = -1; |
| } else{ |
| |
| |
| comres = bma150_smbus_read_byte_block(client, |
| BMA150_ACC_X_LSB__REG, &data[0], 6); |
| |
| acc->x = BMA150_GET_BITSLICE(data[0], BMA150_ACC_X_LSB) | |
| (BMA150_GET_BITSLICE(data[1], BMA150_ACC_X_MSB)<< |
| BMA150_ACC_X_LSB__LEN); |
| acc->x = acc->x << (sizeof(short)*8-(BMA150_ACC_X_LSB__LEN+ |
| BMA150_ACC_X_MSB__LEN)); |
| acc->x = acc->x >> (sizeof(short)*8-(BMA150_ACC_X_LSB__LEN+ |
| BMA150_ACC_X_MSB__LEN)); |
| |
| acc->y = BMA150_GET_BITSLICE(data[2], BMA150_ACC_Y_LSB) | |
| (BMA150_GET_BITSLICE(data[3], BMA150_ACC_Y_MSB)<< |
| BMA150_ACC_Y_LSB__LEN); |
| acc->y = acc->y << (sizeof(short)*8-(BMA150_ACC_Y_LSB__LEN + |
| BMA150_ACC_Y_MSB__LEN)); |
| acc->y = acc->y >> (sizeof(short)*8-(BMA150_ACC_Y_LSB__LEN + |
| BMA150_ACC_Y_MSB__LEN)); |
| |
| |
| acc->z = BMA150_GET_BITSLICE(data[4], BMA150_ACC_Z_LSB); |
| acc->z |= (BMA150_GET_BITSLICE(data[5], BMA150_ACC_Z_MSB)<< |
| BMA150_ACC_Z_LSB__LEN); |
| acc->z = acc->z << (sizeof(short)*8-(BMA150_ACC_Z_LSB__LEN+ |
| BMA150_ACC_Z_MSB__LEN)); |
| acc->z = acc->z >> (sizeof(short)*8-(BMA150_ACC_Z_LSB__LEN+ |
| BMA150_ACC_Z_MSB__LEN)); |
| |
| } |
| |
| return comres; |
| } |
| |
| static void bma150_work_func(struct work_struct *work) |
| { |
| struct bma150_data *bma150 = container_of((struct delayed_work *)work, |
| struct bma150_data, work); |
| static struct bma150acc acc; |
| unsigned long delay = msecs_to_jiffies(atomic_read(&bma150->delay)); |
| |
| |
| |
| bma150_read_accel_xyz(bma150->bma150_client, &acc); |
| input_report_abs(bma150->input, ABS_X, acc.x); |
| input_report_abs(bma150->input, ABS_Y, acc.y); |
| input_report_abs(bma150->input, ABS_Z, acc.z); |
| input_sync(bma150->input); |
| mutex_lock(&bma150->value_mutex); |
| bma150->value = acc; |
| mutex_unlock(&bma150->value_mutex); |
| schedule_delayed_work(&bma150->work, delay); |
| } |
| |
| static ssize_t bma150_mode_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| unsigned char data; |
| struct i2c_client *client = to_i2c_client(dev); |
| struct bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| mutex_lock(&bma150->mode_mutex); |
| data = bma150->mode; |
| mutex_unlock(&bma150->mode_mutex); |
| |
| return sprintf(buf, "%d\n", data); |
| } |
| |
| static ssize_t bma150_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 bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| error = strict_strtoul(buf, 10, &data); |
| if (error) |
| return error; |
| if (bma150_set_mode(bma150->bma150_client, (unsigned char) data) < 0) |
| return -EINVAL; |
| |
| |
| return count; |
| } |
| static ssize_t bma150_range_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| unsigned char data; |
| struct i2c_client *client = to_i2c_client(dev); |
| struct bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| if (bma150_get_range(bma150->bma150_client, &data) < 0) |
| return sprintf(buf, "Read error\n"); |
| |
| return sprintf(buf, "%d\n", data); |
| } |
| |
| static ssize_t bma150_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 bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| error = strict_strtoul(buf, 10, &data); |
| if (error) |
| return error; |
| if (bma150_set_range(bma150->bma150_client, (unsigned char) data) < 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| static ssize_t bma150_bandwidth_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| unsigned char data; |
| struct i2c_client *client = to_i2c_client(dev); |
| struct bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| if (bma150_get_bandwidth(bma150->bma150_client, &data) < 0) |
| return sprintf(buf, "Read error\n"); |
| |
| return sprintf(buf, "%d\n", data); |
| |
| } |
| |
| static ssize_t bma150_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 bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| error = strict_strtoul(buf, 10, &data); |
| if (error) |
| return error; |
| if (bma150_set_bandwidth(bma150->bma150_client, |
| (unsigned char) data) < 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| static ssize_t bma150_value_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct input_dev *input = to_input_dev(dev); |
| struct bma150_data *bma150 = input_get_drvdata(input); |
| struct bma150acc acc_value; |
| |
| mutex_lock(&bma150->value_mutex); |
| acc_value = bma150->value; |
| mutex_unlock(&bma150->value_mutex); |
| |
| return sprintf(buf, "%d %d %d\n", acc_value.x, acc_value.y, |
| acc_value.z); |
| } |
| |
| |
| |
| static ssize_t bma150_delay_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct i2c_client *client = to_i2c_client(dev); |
| struct bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| return sprintf(buf, "%d\n", atomic_read(&bma150->delay)); |
| |
| } |
| |
| static ssize_t bma150_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 bma150_data *bma150 = i2c_get_clientdata(client); |
| |
| error = strict_strtoul(buf, 10, &data); |
| if (error) |
| return error; |
| if (data > BMA150_MAX_DELAY) |
| data = BMA150_MAX_DELAY; |
| atomic_set(&bma150->delay, (unsigned int) data); |
| |
| return count; |
| } |
| |
| static DEVICE_ATTR(range, S_IRUGO|S_IWUSR|S_IWGRP, |
| bma150_range_show, bma150_range_store); |
| static DEVICE_ATTR(bandwidth, S_IRUGO|S_IWUSR|S_IWGRP, |
| bma150_bandwidth_show, bma150_bandwidth_store); |
| static DEVICE_ATTR(mode, S_IRUGO|S_IWUSR|S_IWGRP, |
| bma150_mode_show, bma150_mode_store); |
| static DEVICE_ATTR(value, S_IRUGO|S_IWUSR|S_IWGRP, |
| bma150_value_show, NULL); |
| static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH, |
| bma150_delay_show, bma150_delay_store); |
| |
| static struct attribute *bma150_attributes[] = { |
| &dev_attr_range.attr, |
| &dev_attr_bandwidth.attr, |
| &dev_attr_mode.attr, |
| &dev_attr_value.attr, |
| &dev_attr_delay.attr, |
| NULL |
| }; |
| |
| static struct attribute_group bma150_attribute_group = { |
| .attrs = bma150_attributes |
| }; |
| |
| static int bma150_detect(struct i2c_client *client, |
| struct i2c_board_info *info) |
| { |
| struct i2c_adapter *adapter = client->adapter; |
| |
| if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) |
| return -ENODEV; |
| |
| strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE); |
| |
| return 0; |
| } |
| |
| static int bma150_input_init(struct bma150_data *bma150) |
| { |
| 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, bma150); |
| |
| err = input_register_device(dev); |
| if (err < 0) { |
| input_free_device(dev); |
| return err; |
| } |
| bma150->input = dev; |
| |
| return 0; |
| } |
| |
| static void bma150_input_delete(struct bma150_data *bma150) |
| { |
| struct input_dev *dev = bma150->input; |
| |
| input_unregister_device(dev); |
| input_free_device(dev); |
| } |
| |
| static int bma150_probe(struct i2c_client *client, |
| const struct i2c_device_id *id) |
| { |
| int err = 0; |
| int tempvalue; |
| struct bma150_data *data; |
| |
| if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| printk(KERN_INFO "i2c_check_functionality error\n"); |
| goto exit; |
| } |
| data = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); |
| if (!data) { |
| err = -ENOMEM; |
| goto exit; |
| } |
| |
| i2c_set_clientdata(client, data); |
| data->platform_data = client->dev.platform_data; |
| |
| if (data->platform_data->power_on) |
| data->platform_data->power_on(); |
| else |
| printk(KERN_ERR "power_on function not defined!!\n"); |
| |
| tempvalue = 0; |
| tempvalue = i2c_smbus_read_word_data(client, BMA150_CHIP_ID_REG); |
| |
| if ((tempvalue&0x00FF) == BMA150_CHIP_ID) { |
| printk(KERN_INFO "Bosch Sensortec Device detected!\n" \ |
| "BMA150 registered I2C driver!\n"); |
| } else{ |
| printk(KERN_INFO "Bosch Sensortec Device not found" \ |
| "i2c error %d\n", tempvalue); |
| err = -1; |
| goto kfree_exit; |
| } |
| i2c_set_clientdata(client, data); |
| data->bma150_client = client; |
| mutex_init(&data->value_mutex); |
| mutex_init(&data->mode_mutex); |
| bma150_set_bandwidth(client, BMA150_BW_SET); |
| bma150_set_range(client, BMA150_RANGE_SET); |
| |
| |
| INIT_DELAYED_WORK(&data->work, bma150_work_func); |
| atomic_set(&data->delay, BMA150_MAX_DELAY); |
| err = bma150_input_init(data); |
| if (err < 0) |
| goto kfree_exit; |
| |
| err = sysfs_create_group(&data->input->dev.kobj, |
| &bma150_attribute_group); |
| if (err < 0) |
| goto error_sysfs; |
| |
| schedule_delayed_work(&data->work, |
| msecs_to_jiffies(atomic_read(&data->delay))); |
| |
| return 0; |
| |
| error_sysfs: |
| bma150_input_delete(data); |
| |
| kfree_exit: |
| kfree(data); |
| exit: |
| return err; |
| } |
| |
| static int bma150_suspend(struct i2c_client *client, pm_message_t mesg) |
| { |
| struct bma150_data *data = i2c_get_clientdata(client); |
| |
| cancel_delayed_work_sync(&data->work); |
| |
| bma150_set_mode(client, BMA150_MODE_SLEEP); |
| |
| if ((data->platform_data) && (data->platform_data->power_off)) |
| data->platform_data->power_off(); |
| |
| return 0; |
| } |
| |
| static int bma150_resume(struct i2c_client *client) |
| { |
| struct bma150_data *data = i2c_get_clientdata(client); |
| |
| if ((data->platform_data) && (data->platform_data->power_on)) |
| data->platform_data->power_on(); |
| |
| bma150_set_mode(client, BMA150_MODE_NORMAL); |
| |
| schedule_delayed_work(&data->work, |
| msecs_to_jiffies(atomic_read(&data->delay))); |
| |
| return 0; |
| } |
| |
| static int bma150_remove(struct i2c_client *client) |
| { |
| struct bma150_data *data = i2c_get_clientdata(client); |
| |
| if (data->platform_data->power_off) |
| data->platform_data->power_off(); |
| else |
| printk(KERN_ERR "power_off function not defined!!\n"); |
| |
| sysfs_remove_group(&data->input->dev.kobj, &bma150_attribute_group); |
| bma150_input_delete(data); |
| free_irq(data->IRQ, data); |
| kfree(data); |
| |
| return 0; |
| } |
| |
| static const struct i2c_device_id bma150_id[] = { |
| { SENSOR_NAME, 0 }, |
| { } |
| }; |
| |
| MODULE_DEVICE_TABLE(i2c, bma150_id); |
| |
| static struct i2c_driver bma150_driver = { |
| .driver = { |
| .owner = THIS_MODULE, |
| .name = SENSOR_NAME, |
| }, |
| .class = I2C_CLASS_HWMON, |
| .id_table = bma150_id, |
| .probe = bma150_probe, |
| .remove = bma150_remove, |
| .detect = bma150_detect, |
| .suspend = bma150_suspend, |
| .resume = bma150_resume, |
| }; |
| |
| static int __init BMA150_init(void) |
| { |
| return i2c_add_driver(&bma150_driver); |
| } |
| |
| static void __exit BMA150_exit(void) |
| { |
| i2c_del_driver(&bma150_driver); |
| } |
| |
| MODULE_DESCRIPTION("BMA150 driver"); |
| |
| module_init(BMA150_init); |
| module_exit(BMA150_exit); |
| |