Commit 0bf5a8be4723fd5f243d9d1ed8e6eb9d81f31cf2

Authored by AnilKumar Ch
Committed by Greg Kroah-Hartman
1 parent 7da59d2fe3

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, &reg);
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, &reg);
  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