Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

AnilKumar Ch and committed by
Greg Kroah-Hartman
0bf5a8be 7da59d2f

+87 -9
+2 -1
Documentation/misc-devices/lis3lv02d
··· 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>
+41 -1
drivers/misc/lis3lv02d/lis3lv02d.c
··· 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 ··· 141 133 lis3->read(lis3, reg, &hi); 142 134 /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ 143 135 return (s16)((hi << 8) | lo); 136 + } 137 + 138 + /* 12bits for 2G range, 13 bits for 4G range and 14 bits for 8G range */ 139 + static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg) 140 + { 141 + u8 lo, hi; 142 + int v; 143 + 144 + lis3->read(lis3, reg - 1, &lo); 145 + lis3->read(lis3, reg, &hi); 146 + v = (int) ((hi << 8) | lo); 147 + 148 + return (s16) v >> lis3->shift_adj; 144 149 } 145 150 146 151 /** ··· 216 195 static int lis3_12_rates[4] = {40, 160, 640, 2560}; 217 196 static int lis3_8_rates[2] = {100, 400}; 218 197 static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; 198 + static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; 219 199 220 200 /* ODR is Output Data Rate */ 221 201 static int lis3lv02d_get_odr(struct lis3lv02d *lis3) ··· 289 267 (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); 290 268 } 291 269 292 - if (lis3->whoami == WAI_3DC) { 270 + if ((lis3->whoami == WAI_3DC) || (lis3->whoami == WAI_3DLH)) { 293 271 ctlreg = CTRL_REG4; 294 272 selftest = CTRL4_ST0; 295 273 } else { ··· 420 398 lis3->read(lis3, CTRL_REG2, &reg); 421 399 if (lis3->whoami == WAI_12B) 422 400 reg |= CTRL2_BDU | CTRL2_BOOT; 401 + else if (lis3->whoami == WAI_3DLH) 402 + reg |= CTRL2_BOOT_3DLH; 423 403 else 424 404 reg |= CTRL2_BOOT_8B; 425 405 lis3->write(lis3, CTRL_REG2, reg); 406 + 407 + if (lis3->whoami == WAI_3DLH) { 408 + lis3->read(lis3, CTRL_REG4, &reg); 409 + reg |= CTRL4_BDU; 410 + lis3->write(lis3, CTRL_REG4, reg); 411 + } 426 412 } 427 413 428 414 err = lis3lv02d_get_pwron_wait(lis3); ··· 985 955 lis3->odrs = lis3_3dc_rates; 986 956 lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; 987 957 lis3->scale = LIS3_SENSITIVITY_8B; 958 + break; 959 + case WAI_3DLH: 960 + pr_info("16 bits 3DLH sensor found\n"); 961 + lis3->read_data = lis3lv02d_read_16; 962 + lis3->mdps_max_val = 2048; /* 12 bits for 2G */ 963 + lis3->shift_adj = SHIFT_ADJ_2G; 964 + lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; 965 + lis3->odrs = lis3_3dlh_rates; 966 + lis3->odr_mask = CTRL1_DR0 | CTRL1_DR1; 967 + lis3->scale = LIS3DLH_SENSITIVITY_2G; 988 968 break; 989 969 default: 990 970 pr_err("unknown sensor type 0x%X\n", lis3->whoami);
+38 -6
drivers/misc/lis3lv02d/lis3lv02d.h
··· 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> ··· 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 */ 104 + }; 105 + 106 + enum lis3_type { 107 + LIS3DC, 108 + HP3DC, 109 + LIS3LV02D, 110 + LIS2302D, 111 + LIS331DLF, 112 + LIS331DLH, 103 113 }; 104 114 105 115 enum lis3lv02d_ctrl1_12b { ··· 137 127 CTRL1_ODR1 = 0x20, 138 128 CTRL1_ODR2 = 0x40, 139 129 CTRL1_ODR3 = 0x80, 130 + }; 131 + 132 + enum lis331dlh_ctrl1 { 133 + CTRL1_DR0 = 0x08, 134 + CTRL1_DR1 = 0x10, 135 + CTRL1_PM0 = 0x20, 136 + CTRL1_PM1 = 0x40, 137 + CTRL1_PM2 = 0x80, 138 + }; 139 + 140 + enum lis331dlh_ctrl2 { 141 + CTRL2_HPEN1 = 0x04, 142 + CTRL2_HPEN2 = 0x08, 143 + CTRL2_FDS_3DLH = 0x10, 144 + CTRL2_BOOT_3DLH = 0x80, 145 + }; 146 + 147 + enum lis331dlh_ctrl4 { 148 + CTRL4_STSIGN = 0x08, 149 + CTRL4_BLE = 0x40, 150 + CTRL4_BDU = 0x80, 140 151 }; 141 152 142 153 enum lis3lv02d_ctrl2 { ··· 310 279 int data_ready_count[2]; 311 280 atomic_t wake_thread; 312 281 unsigned char irq_cfg; 282 + unsigned int shift_adj; 313 283 314 284 struct lis3lv02d_platform_data *pdata; /* for passing board config */ 315 285 struct mutex mutex; /* Serialize poll and selftest */
+6 -1
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
··· 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 ··· 236 232 237 233 static const struct i2c_device_id lis3lv02d_id[] = { 238 234 {"lis3lv02d", 0 }, 235 + {"lis331dlh", LIS331DLH}, 239 236 {} 240 237 }; 241 238