aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnilKumar Ch <anilkumar@ti.com>2012-08-22 02:30:39 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-05 16:44:04 -0400
commit0bf5a8be4723fd5f243d9d1ed8e6eb9d81f31cf2 (patch)
treead3c4f0265c8a06c878d2f5918e68bcb2b8dc476
parent7da59d2fe30d8169c7c9e7b488beb1b9af932608 (diff)
lis3lv02d: Add STMicroelectronics lis331dlh digital accelerometer
This patch adds support for lis331dlh digital accelerometer to the lis3lv02d driver family. Adds ID field for detecting the lis331dlh module, based on this ID field lis3lv02d driver will export the lis331dlh module functionality. Signed-off-by: AnilKumar Ch <anilkumar@ti.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/misc-devices/lis3lv02d3
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.c42
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.h44
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c7
4 files changed, 87 insertions, 9 deletions
diff --git a/Documentation/misc-devices/lis3lv02d b/Documentation/misc-devices/lis3lv02d
index f1a4ec840f86..af815b9ba413 100644
--- a/Documentation/misc-devices/lis3lv02d
+++ b/Documentation/misc-devices/lis3lv02d
@@ -4,7 +4,8 @@ Kernel driver lis3lv02d
4Supported chips: 4Supported chips:
5 5
6 * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision) 6 * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
7 * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) 7 * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and
8 LIS331DLH (16 bits)
8 9
9Authors: 10Authors:
10 Yan Burman <burman.yan@gmail.com> 11 Yan Burman <burman.yan@gmail.com>
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index a981e2a42f92..9d37c576d526 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -80,6 +80,14 @@
80#define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) 80#define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024)
81#define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY) 81#define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY)
82 82
83/*
84 * LIS3331DLH spec says 1LSBs corresponds 4G/1024 -> 1LSB is 1000/1024 mG.
85 * Sensitivity values for +/-2G, outdata in 12 bits for +/-2G scale. so 4
86 * bits adjustment is required
87 */
88#define LIS3DLH_SENSITIVITY_2G ((LIS3_ACCURACY * 1000) / 1024)
89#define SHIFT_ADJ_2G 4
90
83#define LIS3_DEFAULT_FUZZ_12B 3 91#define LIS3_DEFAULT_FUZZ_12B 3
84#define LIS3_DEFAULT_FLAT_12B 3 92#define LIS3_DEFAULT_FLAT_12B 3
85#define LIS3_DEFAULT_FUZZ_8B 1 93#define LIS3_DEFAULT_FUZZ_8B 1
@@ -135,6 +143,19 @@ static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
135 return (s16)((hi << 8) | lo); 143 return (s16)((hi << 8) | lo);
136} 144}
137 145
146/* 12bits for 2G range, 13 bits for 4G range and 14 bits for 8G range */
147static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg)
148{
149 u8 lo, hi;
150 int v;
151
152 lis3->read(lis3, reg - 1, &lo);
153 lis3->read(lis3, reg, &hi);
154 v = (int) ((hi << 8) | lo);
155
156 return (s16) v >> lis3->shift_adj;
157}
158
138/** 159/**
139 * lis3lv02d_get_axis - For the given axis, give the value converted 160 * lis3lv02d_get_axis - For the given axis, give the value converted
140 * @axis: 1,2,3 - can also be negative 161 * @axis: 1,2,3 - can also be negative
@@ -195,6 +216,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
195static int lis3_12_rates[4] = {40, 160, 640, 2560}; 216static int lis3_12_rates[4] = {40, 160, 640, 2560};
196static int lis3_8_rates[2] = {100, 400}; 217static int lis3_8_rates[2] = {100, 400};
197static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; 218static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
219static int lis3_3dlh_rates[4] = {50, 100, 400, 1000};
198 220
199/* ODR is Output Data Rate */ 221/* ODR is Output Data Rate */
200static int lis3lv02d_get_odr(struct lis3lv02d *lis3) 222static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
@@ -267,7 +289,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
267 (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); 289 (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
268 } 290 }
269 291
270 if (lis3->whoami == WAI_3DC) { 292 if ((lis3->whoami == WAI_3DC) || (lis3->whoami == WAI_3DLH)) {
271 ctlreg = CTRL_REG4; 293 ctlreg = CTRL_REG4;
272 selftest = CTRL4_ST0; 294 selftest = CTRL4_ST0;
273 } else { 295 } else {
@@ -398,9 +420,17 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3)
398 lis3->read(lis3, CTRL_REG2, &reg); 420 lis3->read(lis3, CTRL_REG2, &reg);
399 if (lis3->whoami == WAI_12B) 421 if (lis3->whoami == WAI_12B)
400 reg |= CTRL2_BDU | CTRL2_BOOT; 422 reg |= CTRL2_BDU | CTRL2_BOOT;
423 else if (lis3->whoami == WAI_3DLH)
424 reg |= CTRL2_BOOT_3DLH;
401 else 425 else
402 reg |= CTRL2_BOOT_8B; 426 reg |= CTRL2_BOOT_8B;
403 lis3->write(lis3, CTRL_REG2, reg); 427 lis3->write(lis3, CTRL_REG2, reg);
428
429 if (lis3->whoami == WAI_3DLH) {
430 lis3->read(lis3, CTRL_REG4, &reg);
431 reg |= CTRL4_BDU;
432 lis3->write(lis3, CTRL_REG4, reg);
433 }
404 } 434 }
405 435
406 err = lis3lv02d_get_pwron_wait(lis3); 436 err = lis3lv02d_get_pwron_wait(lis3);
@@ -956,6 +986,16 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3)
956 lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; 986 lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
957 lis3->scale = LIS3_SENSITIVITY_8B; 987 lis3->scale = LIS3_SENSITIVITY_8B;
958 break; 988 break;
989 case WAI_3DLH:
990 pr_info("16 bits 3DLH sensor found\n");
991 lis3->read_data = lis3lv02d_read_16;
992 lis3->mdps_max_val = 2048; /* 12 bits for 2G */
993 lis3->shift_adj = SHIFT_ADJ_2G;
994 lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
995 lis3->odrs = lis3_3dlh_rates;
996 lis3->odr_mask = CTRL1_DR0 | CTRL1_DR1;
997 lis3->scale = LIS3DLH_SENSITIVITY_2G;
998 break;
959 default: 999 default:
960 pr_err("unknown sensor type 0x%X\n", lis3->whoami); 1000 pr_err("unknown sensor type 0x%X\n", lis3->whoami);
961 return -EINVAL; 1001 return -EINVAL;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
index 2b1482ad3f16..c1a545e136a0 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.h
+++ b/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -26,12 +26,12 @@
26/* 26/*
27 * This driver tries to support the "digital" accelerometer chips from 27 * This driver tries to support the "digital" accelerometer chips from
28 * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, 28 * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
29 * LIS35DE, or LIS202DL. They are very similar in terms of programming, with 29 * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of
30 * almost the same registers. In addition to differing on physical properties, 30 * programming, with almost the same registers. In addition to differing
31 * they differ on the number of axes (2/3), precision (8/12 bits), and special 31 * on physical properties, they differ on the number of axes (2/3),
32 * features (freefall detection, click...). Unfortunately, not all the 32 * precision (8/12 bits), and special features (freefall detection,
33 * differences can be probed via a register. 33 * click...). Unfortunately, not all the differences can be probed via
34 * They can be connected either via I²C or SPI. 34 * a register. They can be connected either via I²C or SPI.
35 */ 35 */
36 36
37#include <linux/lis3lv02d.h> 37#include <linux/lis3lv02d.h>
@@ -96,12 +96,22 @@ enum lis3lv02d_reg {
96}; 96};
97 97
98enum lis3_who_am_i { 98enum lis3_who_am_i {
99 WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */
99 WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ 100 WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */
100 WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ 101 WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
101 WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ 102 WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
102 WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ 103 WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */
103}; 104};
104 105
106enum lis3_type {
107 LIS3DC,
108 HP3DC,
109 LIS3LV02D,
110 LIS2302D,
111 LIS331DLF,
112 LIS331DLH,
113};
114
105enum lis3lv02d_ctrl1_12b { 115enum lis3lv02d_ctrl1_12b {
106 CTRL1_Xen = 0x01, 116 CTRL1_Xen = 0x01,
107 CTRL1_Yen = 0x02, 117 CTRL1_Yen = 0x02,
@@ -129,6 +139,27 @@ enum lis3lv02d_ctrl1_3dc {
129 CTRL1_ODR3 = 0x80, 139 CTRL1_ODR3 = 0x80,
130}; 140};
131 141
142enum lis331dlh_ctrl1 {
143 CTRL1_DR0 = 0x08,
144 CTRL1_DR1 = 0x10,
145 CTRL1_PM0 = 0x20,
146 CTRL1_PM1 = 0x40,
147 CTRL1_PM2 = 0x80,
148};
149
150enum lis331dlh_ctrl2 {
151 CTRL2_HPEN1 = 0x04,
152 CTRL2_HPEN2 = 0x08,
153 CTRL2_FDS_3DLH = 0x10,
154 CTRL2_BOOT_3DLH = 0x80,
155};
156
157enum lis331dlh_ctrl4 {
158 CTRL4_STSIGN = 0x08,
159 CTRL4_BLE = 0x40,
160 CTRL4_BDU = 0x80,
161};
162
132enum lis3lv02d_ctrl2 { 163enum lis3lv02d_ctrl2 {
133 CTRL2_DAS = 0x01, 164 CTRL2_DAS = 0x01,
134 CTRL2_SIM = 0x02, 165 CTRL2_SIM = 0x02,
@@ -279,6 +310,7 @@ struct lis3lv02d {
279 int data_ready_count[2]; 310 int data_ready_count[2];
280 atomic_t wake_thread; 311 atomic_t wake_thread;
281 unsigned char irq_cfg; 312 unsigned char irq_cfg;
313 unsigned int shift_adj;
282 314
283 struct lis3lv02d_platform_data *pdata; /* for passing board config */ 315 struct lis3lv02d_platform_data *pdata; /* for passing board config */
284 struct mutex mutex; /* Serialize poll and selftest */ 316 struct mutex mutex; /* Serialize poll and selftest */
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index e8c0019da97a..15255eb8ac81 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -90,7 +90,11 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
90 if (ret < 0) 90 if (ret < 0)
91 return ret; 91 return ret;
92 92
93 reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; 93 if (lis3->whoami == WAI_3DLH)
94 reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
95 else
96 reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
97
94 return lis3->write(lis3, CTRL_REG1, reg); 98 return lis3->write(lis3, CTRL_REG1, reg);
95} 99}
96 100
@@ -232,6 +236,7 @@ static int lis3_i2c_runtime_resume(struct device *dev)
232 236
233static const struct i2c_device_id lis3lv02d_id[] = { 237static const struct i2c_device_id lis3lv02d_id[] = {
234 {"lis3lv02d", 0 }, 238 {"lis3lv02d", 0 },
239 {"lis331dlh", LIS331DLH},
235 {} 240 {}
236}; 241};
237 242