1198 lines
33 KiB
C
1198 lines
33 KiB
C
|
/* 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 <linux/module.h>
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/i2c.h>
|
||
|
#include <linux/input.h>
|
||
|
#include <linux/workqueue.h>
|
||
|
#include <linux/mutex.h>
|
||
|
#include <linux/slab.h>
|
||
|
#include <linux/mutex.h>
|
||
|
#include "../init-input.h"
|
||
|
|
||
|
//#include <mach/system.h>
|
||
|
//#include <mach/hardware.h>
|
||
|
|
||
|
#if 0
|
||
|
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||
|
#include <linux/earlysuspend.h>
|
||
|
#endif
|
||
|
|
||
|
#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM)
|
||
|
#include <linux/pm.h>
|
||
|
#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<<bitname##__POS)&bitname##__MSK))
|
||
|
|
||
|
|
||
|
/* range and bandwidth */
|
||
|
|
||
|
#define BMA250_RANGE_2G 0
|
||
|
#define BMA250_RANGE_4G 1
|
||
|
#define BMA250_RANGE_8G 2
|
||
|
#define BMA250_RANGE_16G 3
|
||
|
|
||
|
|
||
|
#define BMA250_BW_7_81HZ 0x08
|
||
|
#define BMA250_BW_15_63HZ 0x09
|
||
|
#define BMA250_BW_31_25HZ 0x0A
|
||
|
#define BMA250_BW_62_50HZ 0x0B
|
||
|
#define BMA250_BW_125HZ 0x0C
|
||
|
#define BMA250_BW_250HZ 0x0D
|
||
|
#define BMA250_BW_500HZ 0x0E
|
||
|
#define BMA250_BW_1000HZ 0x0F
|
||
|
|
||
|
/* mode settings */
|
||
|
|
||
|
#define BMA250_MODE_NORMAL 0
|
||
|
#define BMA250_MODE_LOWPOWER 1
|
||
|
#define BMA250_MODE_SUSPEND 2
|
||
|
#define BMA250_MODE_D_SUSPEND 3
|
||
|
|
||
|
struct bma250acc{
|
||
|
s16 x,
|
||
|
y,
|
||
|
z;
|
||
|
} ;
|
||
|
|
||
|
struct bma250_data {
|
||
|
struct i2c_client *bma250_client;
|
||
|
atomic_t delay;
|
||
|
atomic_t enable;
|
||
|
unsigned char mode;
|
||
|
struct input_dev *input;
|
||
|
struct bma250acc value;
|
||
|
struct mutex value_mutex;
|
||
|
struct mutex enable_mutex;
|
||
|
struct mutex mode_mutex;
|
||
|
struct delayed_work work;
|
||
|
struct work_struct irq_work;
|
||
|
|
||
|
#if 0
|
||
|
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||
|
struct early_suspend early_suspend;
|
||
|
#endif
|
||
|
#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM)
|
||
|
unsigned char range_state;
|
||
|
unsigned char bandwidth_state;
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
};
|
||
|
|
||
|
/* Addresses to scan */
|
||
|
static const unsigned short normal_i2c[] = {0x18, I2C_CLIENT_END};
|
||
|
static __u32 twi_id = 0;
|
||
|
static int i2c_num = 0;
|
||
|
unsigned char deep_suspend = 0;
|
||
|
static const unsigned short i2c_address[3] = {0x18,0x19,0x38};
|
||
|
|
||
|
#if 0
|
||
|
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||
|
static void bma250_early_suspend(struct early_suspend *h);
|
||
|
static void bma250_late_resume(struct early_suspend *h);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
static struct sensor_config_info gsensor_info = {
|
||
|
.input_type = GSENSOR_TYPE,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* gsensor_detect - Device detection callback for automatic device creation
|
||
|
* return value:
|
||
|
* = 0; success;
|
||
|
* < 0; err
|
||
|
*/
|
||
|
static int gsensor_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||
|
{
|
||
|
struct i2c_adapter *adapter = client->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)<<BMA250_ACC_X_LSB__LEN);
|
||
|
acc->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)<<BMA250_ACC_Y_LSB__LEN);
|
||
|
acc->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)<<BMA250_ACC_Z_LSB__LEN);
|
||
|
acc->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 <xu.zhang@bosch-sensortec.com>");
|
||
|
MODULE_DESCRIPTION("BMA250 driver");
|
||
|
MODULE_LICENSE("GPL");
|
||
|
|
||
|
module_init(BMA250_init);
|
||
|
module_exit(BMA250_exit);
|
||
|
|