Commit 0bf5a8be4723fd5f243d9d1ed8e6eb9d81f31cf2
Committed by
Greg Kroah-Hartman
1 parent
7da59d2fe3
Exists in
master
and in
20 other branches
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>
Showing 4 changed files with 87 additions and 9 deletions Side-by-side Diff
Documentation/misc-devices/lis3lv02d
... | ... | @@ -4,7 +4,8 @@ |
4 | 4 | Supported chips: |
5 | 5 | |
6 | 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 | |
9 | 10 | Authors: |
10 | 11 | Yan Burman <burman.yan@gmail.com> |
drivers/misc/lis3lv02d/lis3lv02d.c
... | ... | @@ -80,6 +80,14 @@ |
80 | 80 | #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) |
81 | 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 | 91 | #define LIS3_DEFAULT_FUZZ_12B 3 |
84 | 92 | #define LIS3_DEFAULT_FLAT_12B 3 |
85 | 93 | #define LIS3_DEFAULT_FUZZ_8B 1 |
... | ... | @@ -135,6 +143,19 @@ |
135 | 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 */ | |
147 | +static 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 | 160 | * lis3lv02d_get_axis - For the given axis, give the value converted |
140 | 161 | * @axis: 1,2,3 - can also be negative |
... | ... | @@ -195,6 +216,7 @@ |
195 | 216 | static int lis3_12_rates[4] = {40, 160, 640, 2560}; |
196 | 217 | static int lis3_8_rates[2] = {100, 400}; |
197 | 218 | static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; |
219 | +static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; | |
198 | 220 | |
199 | 221 | /* ODR is Output Data Rate */ |
200 | 222 | static int lis3lv02d_get_odr(struct lis3lv02d *lis3) |
... | ... | @@ -267,7 +289,7 @@ |
267 | 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 | 293 | ctlreg = CTRL_REG4; |
272 | 294 | selftest = CTRL4_ST0; |
273 | 295 | } else { |
274 | 296 | |
... | ... | @@ -398,9 +420,17 @@ |
398 | 420 | lis3->read(lis3, CTRL_REG2, ®); |
399 | 421 | if (lis3->whoami == WAI_12B) |
400 | 422 | reg |= CTRL2_BDU | CTRL2_BOOT; |
423 | + else if (lis3->whoami == WAI_3DLH) | |
424 | + reg |= CTRL2_BOOT_3DLH; | |
401 | 425 | else |
402 | 426 | reg |= CTRL2_BOOT_8B; |
403 | 427 | lis3->write(lis3, CTRL_REG2, reg); |
428 | + | |
429 | + if (lis3->whoami == WAI_3DLH) { | |
430 | + lis3->read(lis3, CTRL_REG4, ®); | |
431 | + reg |= CTRL4_BDU; | |
432 | + lis3->write(lis3, CTRL_REG4, reg); | |
433 | + } | |
404 | 434 | } |
405 | 435 | |
406 | 436 | err = lis3lv02d_get_pwron_wait(lis3); |
... | ... | @@ -955,6 +985,16 @@ |
955 | 985 | lis3->odrs = lis3_3dc_rates; |
956 | 986 | lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; |
957 | 987 | lis3->scale = LIS3_SENSITIVITY_8B; |
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; | |
958 | 998 | break; |
959 | 999 | default: |
960 | 1000 | pr_err("unknown sensor type 0x%X\n", lis3->whoami); |
drivers/misc/lis3lv02d/lis3lv02d.h
... | ... | @@ -26,12 +26,12 @@ |
26 | 26 | /* |
27 | 27 | * This driver tries to support the "digital" accelerometer chips from |
28 | 28 | * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, |
29 | - * LIS35DE, or LIS202DL. They are very similar in terms of programming, with | |
30 | - * almost the same registers. In addition to differing on physical properties, | |
31 | - * they differ on the number of axes (2/3), precision (8/12 bits), and special | |
32 | - * features (freefall detection, click...). Unfortunately, not all the | |
33 | - * differences can be probed via a register. | |
34 | - * They can be connected either via IยฒC or SPI. | |
29 | + * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of | |
30 | + * programming, with almost the same registers. In addition to differing | |
31 | + * on physical properties, they differ on the number of axes (2/3), | |
32 | + * precision (8/12 bits), and special features (freefall detection, | |
33 | + * click...). Unfortunately, not all the differences can be probed via | |
34 | + * a register. They can be connected either via IยฒC or SPI. | |
35 | 35 | */ |
36 | 36 | |
37 | 37 | #include <linux/lis3lv02d.h> |
38 | 38 | |
... | ... | @@ -96,12 +96,22 @@ |
96 | 96 | }; |
97 | 97 | |
98 | 98 | enum lis3_who_am_i { |
99 | + WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */ | |
99 | 100 | WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ |
100 | 101 | WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ |
101 | 102 | WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ |
102 | 103 | WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ |
103 | 104 | }; |
104 | 105 | |
106 | +enum lis3_type { | |
107 | + LIS3DC, | |
108 | + HP3DC, | |
109 | + LIS3LV02D, | |
110 | + LIS2302D, | |
111 | + LIS331DLF, | |
112 | + LIS331DLH, | |
113 | +}; | |
114 | + | |
105 | 115 | enum lis3lv02d_ctrl1_12b { |
106 | 116 | CTRL1_Xen = 0x01, |
107 | 117 | CTRL1_Yen = 0x02, |
... | ... | @@ -129,6 +139,27 @@ |
129 | 139 | CTRL1_ODR3 = 0x80, |
130 | 140 | }; |
131 | 141 | |
142 | +enum lis331dlh_ctrl1 { | |
143 | + CTRL1_DR0 = 0x08, | |
144 | + CTRL1_DR1 = 0x10, | |
145 | + CTRL1_PM0 = 0x20, | |
146 | + CTRL1_PM1 = 0x40, | |
147 | + CTRL1_PM2 = 0x80, | |
148 | +}; | |
149 | + | |
150 | +enum lis331dlh_ctrl2 { | |
151 | + CTRL2_HPEN1 = 0x04, | |
152 | + CTRL2_HPEN2 = 0x08, | |
153 | + CTRL2_FDS_3DLH = 0x10, | |
154 | + CTRL2_BOOT_3DLH = 0x80, | |
155 | +}; | |
156 | + | |
157 | +enum lis331dlh_ctrl4 { | |
158 | + CTRL4_STSIGN = 0x08, | |
159 | + CTRL4_BLE = 0x40, | |
160 | + CTRL4_BDU = 0x80, | |
161 | +}; | |
162 | + | |
132 | 163 | enum lis3lv02d_ctrl2 { |
133 | 164 | CTRL2_DAS = 0x01, |
134 | 165 | CTRL2_SIM = 0x02, |
... | ... | @@ -279,6 +310,7 @@ |
279 | 310 | int data_ready_count[2]; |
280 | 311 | atomic_t wake_thread; |
281 | 312 | unsigned char irq_cfg; |
313 | + unsigned int shift_adj; | |
282 | 314 | |
283 | 315 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ |
284 | 316 | struct mutex mutex; /* Serialize poll and selftest */ |
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
... | ... | @@ -90,7 +90,11 @@ |
90 | 90 | if (ret < 0) |
91 | 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 | 98 | return lis3->write(lis3, CTRL_REG1, reg); |
95 | 99 | } |
96 | 100 | |
... | ... | @@ -232,6 +236,7 @@ |
232 | 236 | |
233 | 237 | static const struct i2c_device_id lis3lv02d_id[] = { |
234 | 238 | {"lis3lv02d", 0 }, |
239 | + {"lis331dlh", LIS331DLH}, | |
235 | 240 | {} |
236 | 241 | }; |
237 | 242 |