Commit 78537c3b authored by Takashi Iwai's avatar Takashi Iwai Committed by Guenter Roeck

hwmon: (lis3) Add support for new LIS3DC / HP3DC chip

A new version of LIS3 chip has slight incompatibilities from former
versions.  This patch adds the minimal support for it.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarGuenter Roeck <guenter.roeck@ericsson.com>
parent 9401ba13
...@@ -138,6 +138,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) ...@@ -138,6 +138,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
/* conversion btw sampling rate and the register values */ /* conversion btw sampling rate and the register values */
static int lis3_12_rates[4] = {40, 160, 640, 2560}; static int lis3_12_rates[4] = {40, 160, 640, 2560};
static int lis3_8_rates[2] = {100, 400}; static int lis3_8_rates[2] = {100, 400};
static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
/* ODR is Output Data Rate */ /* ODR is Output Data Rate */
static int lis3lv02d_get_odr(void) static int lis3lv02d_get_odr(void)
...@@ -156,6 +157,9 @@ static int lis3lv02d_set_odr(int rate) ...@@ -156,6 +157,9 @@ static int lis3lv02d_set_odr(int rate)
u8 ctrl; u8 ctrl;
int i, len, shift; int i, len, shift;
if (!rate)
return -EINVAL;
lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
ctrl &= ~lis3_dev.odr_mask; ctrl &= ~lis3_dev.odr_mask;
len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */ len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
...@@ -172,19 +176,25 @@ static int lis3lv02d_set_odr(int rate) ...@@ -172,19 +176,25 @@ static int lis3lv02d_set_odr(int rate)
static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
{ {
u8 reg; u8 ctlreg, reg;
s16 x, y, z; s16 x, y, z;
u8 selftest; u8 selftest;
int ret; int ret;
mutex_lock(&lis3->mutex); mutex_lock(&lis3->mutex);
if (lis3_dev.whoami == WAI_3DC) {
ctlreg = CTRL_REG4;
selftest = CTRL4_ST0;
} else {
ctlreg = CTRL_REG1;
if (lis3_dev.whoami == WAI_12B) if (lis3_dev.whoami == WAI_12B)
selftest = CTRL1_ST; selftest = CTRL1_ST;
else else
selftest = CTRL1_STP; selftest = CTRL1_STP;
}
lis3->read(lis3, CTRL_REG1, &reg); lis3->read(lis3, ctlreg, &reg);
lis3->write(lis3, CTRL_REG1, (reg | selftest)); lis3->write(lis3, ctlreg, (reg | selftest));
msleep(lis3->pwron_delay / lis3lv02d_get_odr()); msleep(lis3->pwron_delay / lis3lv02d_get_odr());
/* Read directly to avoid axis remap */ /* Read directly to avoid axis remap */
...@@ -193,7 +203,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) ...@@ -193,7 +203,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
z = lis3->read_data(lis3, OUTZ); z = lis3->read_data(lis3, OUTZ);
/* back to normal settings */ /* back to normal settings */
lis3->write(lis3, CTRL_REG1, reg); lis3->write(lis3, ctlreg, reg);
msleep(lis3->pwron_delay / lis3lv02d_get_odr()); msleep(lis3->pwron_delay / lis3lv02d_get_odr());
results[0] = x - lis3->read_data(lis3, OUTX); results[0] = x - lis3->read_data(lis3, OUTX);
...@@ -674,6 +684,15 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) ...@@ -674,6 +684,15 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
dev->odr_mask = CTRL1_DR; dev->odr_mask = CTRL1_DR;
dev->scale = LIS3_SENSITIVITY_8B; dev->scale = LIS3_SENSITIVITY_8B;
break; break;
case WAI_3DC:
printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
dev->read_data = lis3lv02d_read_8;
dev->mdps_max_val = 128;
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
dev->odrs = lis3_3dc_rates;
dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
dev->scale = LIS3_SENSITIVITY_8B;
break;
default: default:
printk(KERN_ERR DRIVER_NAME printk(KERN_ERR DRIVER_NAME
": unknown sensor type 0x%X\n", dev->whoami); ": unknown sensor type 0x%X\n", dev->whoami);
......
...@@ -45,6 +45,7 @@ enum lis3_reg { ...@@ -45,6 +45,7 @@ enum lis3_reg {
CTRL_REG1 = 0x20, CTRL_REG1 = 0x20,
CTRL_REG2 = 0x21, CTRL_REG2 = 0x21,
CTRL_REG3 = 0x22, CTRL_REG3 = 0x22,
CTRL_REG4 = 0x23,
HP_FILTER_RESET = 0x23, HP_FILTER_RESET = 0x23,
STATUS_REG = 0x27, STATUS_REG = 0x27,
OUTX_L = 0x28, OUTX_L = 0x28,
...@@ -93,6 +94,7 @@ enum lis3lv02d_reg { ...@@ -93,6 +94,7 @@ enum lis3lv02d_reg {
}; };
enum lis3_who_am_i { enum lis3_who_am_i {
WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */
WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */
...@@ -118,6 +120,13 @@ enum lis3lv02d_ctrl1_8b { ...@@ -118,6 +120,13 @@ enum lis3lv02d_ctrl1_8b {
CTRL1_DR = 0x80, CTRL1_DR = 0x80,
}; };
enum lis3lv02d_ctrl1_3dc {
CTRL1_ODR0 = 0x10,
CTRL1_ODR1 = 0x20,
CTRL1_ODR2 = 0x40,
CTRL1_ODR3 = 0x80,
};
enum lis3lv02d_ctrl2 { enum lis3lv02d_ctrl2 {
CTRL2_DAS = 0x01, CTRL2_DAS = 0x01,
CTRL2_SIM = 0x02, CTRL2_SIM = 0x02,
...@@ -129,6 +138,14 @@ enum lis3lv02d_ctrl2 { ...@@ -129,6 +138,14 @@ enum lis3lv02d_ctrl2 {
CTRL2_FS = 0x80, /* Full Scale selection */ CTRL2_FS = 0x80, /* Full Scale selection */
}; };
enum lis3lv02d_ctrl4_3dc {
CTRL4_SIM = 0x01,
CTRL4_ST0 = 0x02,
CTRL4_ST1 = 0x04,
CTRL4_FS0 = 0x10,
CTRL4_FS1 = 0x20,
};
enum lis302d_ctrl2 { enum lis302d_ctrl2 {
HP_FF_WU2 = 0x08, HP_FF_WU2 = 0x08,
HP_FF_WU1 = 0x04, HP_FF_WU1 = 0x04,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment