misc: l3g4200d: update gyro register set and general cleanup

Change-Id: I17c2384842e1528c4dbdedb094e79de3c44ac5ee
Signed-off-by: makarand.karvekar <makarand.karvekar@motorola.com>
This commit is contained in:
makarand.karvekar 2011-01-07 10:39:34 -06:00 committed by Rebecca Schultz Zavin
parent 6837ab86cc
commit ee28cc2854
2 changed files with 86 additions and 224 deletions

View File

@ -30,8 +30,6 @@
#include <linux/l3g4200d.h>
#define DEBUG 1
/** Register map */
#define L3G4200D_WHO_AM_I 0x0f
#define L3G4200D_CTRL_REG1 0x20
@ -41,6 +39,7 @@
#define L3G4200D_CTRL_REG5 0x24
#define L3G4200D_REF_DATA_CAP 0x25
#define L3G4200D_OUT_TEMP 0x26
#define L3G4200D_STATUS_REG 0x27
#define L3G4200D_OUT_X_L 0x28
@ -50,6 +49,9 @@
#define L3G4200D_OUT_Z_L 0x2c
#define L3G4200D_OUT_Z_H 0x2d
#define L3G4200D_FIFO_CTRL 0x2e
#define L3G4200D_FIFO_SRC 0x2e
#define L3G4200D_INTERRUPT_CFG 0x30
#define L3G4200D_INTERRUPT_SRC 0x31
#define L3G4200D_INTERRUPT_THRESH_X_H 0x32
@ -66,17 +68,9 @@
#define I2C_RETRY_DELAY 5
#define I2C_RETRIES 5
#define AUTO_INCREMENT 0x80
#define ODRHALF 0x40 /* 0.5Hz output data rate */
#define ODR1 0x60 /* 1Hz output data rate */
#define ODR2 0x80 /* 2Hz output data rate */
#define ODR5 0xA0 /* 5Hz output data rate */
#define ODR10 0xC0 /* 10Hz output data rate */
#define ODR50 0x00 /* 50Hz output data rate */
#define ODR100 0x08 /* 100Hz output data rate */
#define ODR400 0x10 /* 400Hz output data rate */
#define ODR1000 0x18 /* 1000Hz output data rate */
#define L3G4200D_PU_DELAY 300
struct l3g4200d_data {
struct i2c_client *client;
struct l3g4200d_platform_data *pdata;
@ -91,38 +85,14 @@ struct l3g4200d_data {
u8 shift_adj;
u8 resume_state[5];
u8 multiplier;
};
#ifdef DEBUG
struct l3g4200d_reg {
const char *name;
uint8_t reg;
} l3g4200d_regs[] = {
{ "WHO_AM_I", L3G4200D_WHO_AM_I },
{ "CNTRL_1", L3G4200D_CTRL_REG1 },
{ "CNTRL_2", L3G4200D_CTRL_REG2 },
{ "CNTRL_3", L3G4200D_CTRL_REG3 },
{ "CNTRL_4", L3G4200D_CTRL_REG4 },
{ "CNTRL_5", L3G4200D_CTRL_REG5 },
{ "REF_DATA_CAP", L3G4200D_REF_DATA_CAP },
{ "STATUS_REG", L3G4200D_STATUS_REG },
{ "INT_CFG", L3G4200D_INTERRUPT_CFG },
{ "INT_SRC", L3G4200D_INTERRUPT_SRC },
{ "INT_TH_X_H", L3G4200D_INTERRUPT_THRESH_X_H },
{ "INT_TH_X_L", L3G4200D_INTERRUPT_THRESH_X_L },
{ "INT_TH_Y_H", L3G4200D_INTERRUPT_THRESH_Y_H },
{ "INT_TH_Y_L", L3G4200D_INTERRUPT_THRESH_Y_L },
{ "INT_TH_Z_H", L3G4200D_INTERRUPT_THRESH_Z_H },
{ "INT_TH_Z_L", L3G4200D_INTERRUPT_THRESH_Z_L },
{ "INT_DUR", L3G4200D_INTERRUPT_DURATION },
{ "OUT_X_H", L3G4200D_OUT_X_H },
{ "OUT_X_L", L3G4200D_OUT_X_L },
{ "OUT_Y_H", L3G4200D_OUT_Y_H },
{ "OUT_Y_L", L3G4200D_OUT_Y_L },
{ "OUT_Z_H", L3G4200D_OUT_Z_H },
{ "OUT_Z_L", L3G4200D_OUT_Z_L },
struct gyro_val {
s16 x;
s16 y;
s16 z;
};
#endif
static uint32_t l3g4200d_debug;
module_param_named(gyro_debug, l3g4200d_debug, uint, 0664);
@ -198,19 +168,44 @@ static int l3g4200d_i2c_write(struct l3g4200d_data *gyro, u8 * buf, int len)
static int l3g4200d_hw_init(struct l3g4200d_data *gyro)
{
int err = -1;
u8 buf[6];
u8 buf[8];
buf[0] = (AUTO_INCREMENT | L3G4200D_CTRL_REG1);
buf[1] = gyro->resume_state[0];
buf[2] = gyro->resume_state[1];
buf[3] = gyro->resume_state[2];
buf[4] = gyro->resume_state[3];
buf[5] = gyro->resume_state[4];
err = l3g4200d_i2c_write(gyro, buf, 5);
buf[1] = gyro->pdata->ctrl_reg1;
buf[2] = gyro->pdata->ctrl_reg2;
buf[3] = gyro->pdata->ctrl_reg3;
buf[4] = gyro->pdata->ctrl_reg4;
buf[5] = gyro->pdata->ctrl_reg5;
buf[6] = gyro->pdata->reference;
err = l3g4200d_i2c_write(gyro, buf, 6);
if (err < 0)
return err;
gyro->hw_initialized = 1;
buf[0] = (L3G4200D_FIFO_CTRL);
buf[1] = gyro->pdata->fifo_ctrl_reg;
err = l3g4200d_i2c_write(gyro, buf, 1);
if (err < 0)
return err;
buf[0] = (L3G4200D_INTERRUPT_CFG);
buf[1] = gyro->pdata->int1_cfg;
err = l3g4200d_i2c_write(gyro, buf, 1);
if (err < 0)
return err;
buf[0] = (AUTO_INCREMENT | L3G4200D_INTERRUPT_THRESH_X_H);
buf[1] = gyro->pdata->int1_tsh_xh;
buf[2] = gyro->pdata->int1_tsh_xl;
buf[3] = gyro->pdata->int1_tsh_yh;
buf[4] = gyro->pdata->int1_tsh_yl;
buf[5] = gyro->pdata->int1_tsh_zh;
buf[6] = gyro->pdata->int1_tsh_zl;
buf[7] = gyro->pdata->int1_duration;
err = l3g4200d_i2c_write(gyro, buf, 7);
if (err < 0)
return err;
gyro->hw_initialized = true;
return 0;
}
@ -218,15 +213,15 @@ static int l3g4200d_hw_init(struct l3g4200d_data *gyro)
static void l3g4200d_device_power_off(struct l3g4200d_data *gyro)
{
int err;
u8 buf[2] = {L3G4200D_CTRL_REG1,0 };
u8 buf[2] = {L3G4200D_CTRL_REG1, 0};
err = l3g4200d_i2c_read(gyro, buf, 1);
if (err < 0){
if (err < 0) {
dev_err(&gyro->client->dev, "read register control_1 failed\n");
return ;
}
buf[1] = buf[0] & ~PM_MASK;
buf[0] = L3G4200D_CTRL_REG1;
return;
}
buf[1] = buf[0] & ~PM_MASK;
buf[0] = L3G4200D_CTRL_REG1;
err = l3g4200d_i2c_write(gyro, buf, 1);
if (err < 0)
@ -234,7 +229,7 @@ static void l3g4200d_device_power_off(struct l3g4200d_data *gyro)
if (gyro->regulator) {
regulator_disable(gyro->regulator);
gyro->hw_initialized = 0;
gyro->hw_initialized = false;
}
}
@ -259,8 +254,8 @@ static int l3g4200d_device_power_on(struct l3g4200d_data *gyro)
err = l3g4200d_i2c_read(gyro, buf, 1);
if (err < 0)
dev_err(&gyro->client->dev, "read register control_1 failed\n");
buf[1] = buf[0] | PM_MASK;
buf[0] = L3G4200D_CTRL_REG1;
buf[1] = buf[0] | PM_MASK;
buf[0] = L3G4200D_CTRL_REG1;
err = l3g4200d_i2c_write(gyro, buf, 1);
if (err < 0)
@ -268,46 +263,35 @@ static int l3g4200d_device_power_on(struct l3g4200d_data *gyro)
return 0;
}
static int l3g4200d_get_gyro_data(struct l3g4200d_data *gyro, int *xyz)
static int l3g4200d_get_gyro_data(struct l3g4200d_data *gyro,
struct gyro_val *data)
{
int err = -1;
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
u8 gyro_data[6];
/* x,y,z hardware data */
int hw_d[3] = { 0 };
gyro_data[0] = (AUTO_INCREMENT | L3G4200D_OUT_X_L);
err = l3g4200d_i2c_read(gyro, gyro_data, 6);
if (err < 0)
return err;
hw_d[0] = (int) (((gyro_data[1]) << 8) | gyro_data[0]);
hw_d[1] = (int) (((gyro_data[3]) << 8) | gyro_data[2]);
hw_d[2] = (int) (((gyro_data[5]) << 8) | gyro_data[4]);
data->x = (gyro_data[1] << 8) | gyro_data[0];
data->y = (gyro_data[3] << 8) | gyro_data[2];
data->z = (gyro_data[5] << 8) | gyro_data[4];
hw_d[0] = (hw_d[0] & 0x8000) ? (hw_d[0] | 0xFFFF0000) : (hw_d[0]);
hw_d[1] = (hw_d[1] & 0x8000) ? (hw_d[1] | 0xFFFF0000) : (hw_d[1]);
hw_d[2] = (hw_d[2] & 0x8000) ? (hw_d[2] | 0xFFFF0000) : (hw_d[2]);
xyz[0] = ((gyro->pdata->negate_x) ? (-hw_d[gyro->pdata->axis_map_x])
: (hw_d[gyro->pdata->axis_map_x])) * gyro->multiplier;
xyz[1] = ((gyro->pdata->negate_y) ? (-hw_d[gyro->pdata->axis_map_y])
: (hw_d[gyro->pdata->axis_map_y])) * gyro->multiplier;
xyz[2] = ((gyro->pdata->negate_z) ? (-hw_d[gyro->pdata->axis_map_z])
: (hw_d[gyro->pdata->axis_map_z])) * gyro->multiplier;
return err;
return 0;
}
static void l3g4200d_report_values(struct l3g4200d_data *gyro, int *xyz)
static void l3g4200d_report_values(struct l3g4200d_data *gyro,
struct gyro_val *data)
{
input_report_rel(gyro->input_dev, REL_RX, xyz[0]);
input_report_rel(gyro->input_dev, REL_RY, xyz[1]);
input_report_rel(gyro->input_dev, REL_RZ, xyz[2]);
input_report_rel(gyro->input_dev, REL_RX, data->x);
input_report_rel(gyro->input_dev, REL_RY, data->y);
input_report_rel(gyro->input_dev, REL_RZ, data->z);
if (l3g4200d_debug)
pr_info("%s: Reporting x: %d, y: %d, z: %d\n",
__func__, xyz[0], xyz[1], xyz[2]);
__func__, data->x, data->y, data->z);
input_sync(gyro->input_dev);
}
@ -366,10 +350,8 @@ static long l3g4200d_misc_ioctl(struct file *file,
break;
case L3G4200D_IOCTL_SET_DELAY:
if (copy_from_user(&interval, argp, sizeof(interval))) {
gyro->pdata->poll_interval = 0;
if (copy_from_user(&interval, argp, sizeof(interval)))
return -EFAULT;
}
gyro->pdata->poll_interval =
max(interval, gyro->pdata->min_interval);
break;
@ -418,89 +400,19 @@ static void l3g4200d_input_work_func(struct work_struct *work)
struct l3g4200d_data *gyro = container_of((struct delayed_work *)work,
struct l3g4200d_data,
input_work);
int xyz[3] = { 0 };
struct gyro_val data;
int err;
err = l3g4200d_get_gyro_data(gyro, xyz);
err = l3g4200d_get_gyro_data(gyro, &data);
if (err < 0)
dev_err(&gyro->client->dev, "get_acceleration_data failed\n");
else
l3g4200d_report_values(gyro, xyz);
l3g4200d_report_values(gyro, &data);
schedule_delayed_work(&gyro->input_work,
msecs_to_jiffies(gyro->pdata->poll_interval));
}
#ifdef DEBUG
static ssize_t l3g4200d_registers_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = container_of(dev, struct i2c_client,
dev);
struct l3g4200d_data *gyro = i2c_get_clientdata(client);
u8 l3g4200d_buf[2];
unsigned i, n, reg_count;
reg_count = sizeof(l3g4200d_regs) / sizeof(l3g4200d_regs[0]);
for (i = 0, n = 0; i < reg_count; i++) {
l3g4200d_buf[0] = (AUTO_INCREMENT | l3g4200d_regs[i].reg);
l3g4200d_i2c_read(gyro, l3g4200d_buf, 1);
n += scnprintf(buf + n, PAGE_SIZE - n,
"%-20s = 0x%02X\n",
l3g4200d_regs[i].name, l3g4200d_buf[0]);
}
return n;
}
static ssize_t l3g4200d_registers_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = container_of(dev, struct i2c_client,
dev);
struct l3g4200d_data *gyro = i2c_get_clientdata(client);
unsigned i, reg_count, value;
int error;
u8 l3g4200d_buf[2];
char name[30];
if (count >= 30) {
pr_err("%s:input too long\n", __func__);
return -1;
}
if (sscanf(buf, "%s %x", name, &value) != 2) {
pr_err("%s:unable to parse input\n", __func__);
return -1;
}
reg_count = sizeof(l3g4200d_regs) / sizeof(l3g4200d_regs[0]);
for (i = 0; i < reg_count; i++) {
if (!strcmp(name, l3g4200d_regs[i].name)) {
l3g4200d_buf[0] = (AUTO_INCREMENT | l3g4200d_regs[i].reg);
l3g4200d_buf[1] = value;
error = l3g4200d_i2c_write(gyro, l3g4200d_buf, 2);
if (error) {
pr_err("%s:Failed to write register %s\n",
__func__, name);
return -1;
}
return count;
}
}
if (!strcmp("Go", name)) {
l3g4200d_enable(gyro);
return 0;
}
if (!strcmp("Stop", name)) {
l3g4200d_disable(gyro);
return 0;
}
pr_err("%s:no such register %s\n", __func__, name);
return -1;
}
static DEVICE_ATTR(registers, 0644, l3g4200d_registers_show,
l3g4200d_registers_store);
#endif
#ifdef L3G4200D_OPEN_ENABLE
int l3g4200d_input_open(struct input_dev *input)
{
@ -522,25 +434,6 @@ static int l3g4200d_validate_pdata(struct l3g4200d_data *gyro)
gyro->pdata->poll_interval = max(gyro->pdata->poll_interval,
gyro->pdata->min_interval);
if (gyro->pdata->axis_map_x > 2 ||
gyro->pdata->axis_map_y > 2 || gyro->pdata->axis_map_z > 2) {
dev_err(&gyro->client->dev,
"invalid axis_map value x:%u y:%u z%u\n",
gyro->pdata->axis_map_x, gyro->pdata->axis_map_y,
gyro->pdata->axis_map_z);
return -EINVAL;
}
/* Only allow 0 and 1 for negation boolean flag */
if (gyro->pdata->negate_x > 1 || gyro->pdata->negate_y > 1 ||
gyro->pdata->negate_z > 1) {
dev_err(&gyro->client->dev,
"invalid negate value x:%u y:%u z:%u\n",
gyro->pdata->negate_x, gyro->pdata->negate_y,
gyro->pdata->negate_z);
return -EINVAL;
}
/* Enforce minimum polling interval */
if (gyro->pdata->poll_interval < gyro->pdata->min_interval) {
dev_err(&gyro->client->dev, "minimum poll interval violated\n");
@ -603,7 +496,6 @@ static int l3g4200d_probe(struct i2c_client *client,
{
struct l3g4200d_data *gyro;
int err = -1;
u8 full_scale;
pr_err("%s:Enter\n", __func__);
if (client->dev.platform_data == NULL) {
@ -648,14 +540,6 @@ static int l3g4200d_probe(struct i2c_client *client,
i2c_set_clientdata(client, gyro);
memset(gyro->resume_state, 0, ARRAY_SIZE(gyro->resume_state));
gyro->resume_state[0] = gyro->pdata->ctrl_reg_1;
gyro->resume_state[1] = gyro->pdata->ctrl_reg_2;
gyro->resume_state[2] = gyro->pdata->ctrl_reg_3;
gyro->resume_state[3] = gyro->pdata->ctrl_reg_4;
gyro->resume_state[4] = gyro->pdata->ctrl_reg_5;
/* As default, do not report information */
atomic_set(&gyro->enabled, 0);
@ -670,21 +554,8 @@ static int l3g4200d_probe(struct i2c_client *client,
dev_err(&client->dev, "l3g4200d_device register failed\n");
goto err4;
}
#ifdef DEBUG
err = device_create_file(&client->dev, &dev_attr_registers);
if (err < 0)
pr_err("%s:File device creation failed: %d\n", __func__, err);
#endif
full_scale = gyro->pdata->ctrl_reg_4 & 0x30;
if ( full_scale == 0x00)
gyro->multiplier = 1;
if ( full_scale == 0x10)
gyro->multiplier = 2;
if ((full_scale == 0x20) || (full_scale == 0x30))
gyro->multiplier = 8;
pr_info("%s: multiplier %d\n", __func__, gyro->multiplier);
pr_err("%s:Gyro probed\n", __func__);
pr_info("%s:Gyro probed\n", __func__);
return 0;
err4:
@ -704,9 +575,6 @@ static int __devexit l3g4200d_remove(struct i2c_client *client)
{
struct l3g4200d_data *gyro = i2c_get_clientdata(client);
#ifdef DEBUG
device_remove_file(&client->dev, &dev_attr_registers);
#endif
misc_deregister(&l3g4200d_misc_device);
l3g4200d_input_cleanup(gyro);
l3g4200d_disable(gyro);

View File

@ -36,31 +36,25 @@ struct l3g4200d_platform_data {
int poll_interval;
int min_interval;
u8 ctrl_reg_1;
u8 ctrl_reg_2;
u8 ctrl_reg_3;
u8 ctrl_reg_4;
u8 ctrl_reg_5;
u8 ctrl_reg1;
u8 ctrl_reg2;
u8 ctrl_reg3;
u8 ctrl_reg4;
u8 ctrl_reg5;
u8 int_config;
u8 int_source;
u8 reference;
u8 int_th_x_h;
u8 int_th_x_l;
u8 int_th_y_h;
u8 int_th_y_l;
u8 int_th_z_h;
u8 int_th_z_l;
u8 int_duration;
u8 fifo_ctrl_reg;
u8 axis_map_x;
u8 axis_map_y;
u8 axis_map_z;
u8 negate_x;
u8 negate_y;
u8 negate_z;
u8 int1_cfg;
u8 int1_tsh_xh;
u8 int1_tsh_xl;
u8 int1_tsh_yh;
u8 int1_tsh_yl;
u8 int1_tsh_zh;
u8 int1_tsh_zl;
u8 int1_duration;
};
#endif /* __KERNEL__ */