Commit 4903a2ddb73cb7315cb0b42fc1c354c6bad04bff
1 parent
565a55c815
Exists in
master
lis3lv02d: Add STMicroelectronics lis33ldlh digital accelerometer
This patch adds support for lis33ldlh digital accelerometer to the lis3lv02d driver family. Adds ID field for detecting the lis33ldlh module, based on this ID field lis3lv02d driver will export the lis33ldlh module functionality. Also exports g_range parameter to user space for run-time value change. User must give 2/4/8 value depends on requirement. Signed-off-by: Anil Kumar Ch <anilkumar@ti.com>
Showing 4 changed files with 173 additions and 5 deletions Side-by-side Diff
drivers/misc/lis3lv02d/lis3lv02d.c
... | ... | @@ -80,6 +80,17 @@ |
80 | 80 | #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) |
81 | 81 | #define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY) |
82 | 82 | |
83 | +/* Sensitivity values for -2G, -4G, -8G and +2G, +4G, +8G scale */ | |
84 | +#define LIS3DLH_SENSITIVITY_2G (LIS3_ACCURACY * 1) | |
85 | +#define LIS3DLH_SENSITIVITY_4G (LIS3_ACCURACY * 2) | |
86 | +#define LIS3DLH_SENSITIVITY_8G ((LIS3_ACCURACY * 39)/10) | |
87 | + | |
88 | +#define SHIFT_ADJ_2G 4 | |
89 | +#define SHIFT_ADJ_4G 3 | |
90 | +#define SHIFT_ADJ_8G 2 | |
91 | + | |
92 | +#define FS_MASK (0x3 << 4) | |
93 | + | |
83 | 94 | #define LIS3_DEFAULT_FUZZ_12B 3 |
84 | 95 | #define LIS3_DEFAULT_FLAT_12B 3 |
85 | 96 | #define LIS3_DEFAULT_FUZZ_8B 1 |
... | ... | @@ -148,6 +159,12 @@ |
148 | 159 | return -hw_values[-axis - 1]; |
149 | 160 | } |
150 | 161 | |
162 | +static int lis3lv02d_decode(u8 pl, u8 ph, int adj) | |
163 | +{ | |
164 | + s16 v = pl | ph << 8; | |
165 | + return (int) v >> adj; | |
166 | +} | |
167 | + | |
151 | 168 | /** |
152 | 169 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer |
153 | 170 | * @lis3: pointer to the device struct |
... | ... | @@ -176,9 +193,24 @@ |
176 | 193 | position[i] = (s8)data[i * 2]; |
177 | 194 | } |
178 | 195 | } else { |
179 | - position[0] = lis3->read_data(lis3, OUTX); | |
180 | - position[1] = lis3->read_data(lis3, OUTY); | |
181 | - position[2] = lis3->read_data(lis3, OUTZ); | |
196 | + if (lis3_dev.whoami == WAI_3DLH) { | |
197 | + position[0] = | |
198 | + lis3lv02d_decode(lis3->read_data(lis3, OUTX_L), | |
199 | + lis3->read_data(lis3, OUTX_H), | |
200 | + lis3_dev.shift_adj); | |
201 | + position[1] = | |
202 | + lis3lv02d_decode(lis3->read_data(lis3, OUTY_L), | |
203 | + lis3->read_data(lis3, OUTY_H), | |
204 | + lis3_dev.shift_adj); | |
205 | + position[2] = | |
206 | + lis3lv02d_decode(lis3->read_data(lis3, OUTZ_L), | |
207 | + lis3->read_data(lis3, OUTZ_H), | |
208 | + lis3_dev.shift_adj); | |
209 | + } else { | |
210 | + position[0] = lis3->read_data(lis3, OUTX); | |
211 | + position[1] = lis3->read_data(lis3, OUTY); | |
212 | + position[2] = lis3->read_data(lis3, OUTZ); | |
213 | + } | |
182 | 214 | } |
183 | 215 | |
184 | 216 | for (i = 0; i < 3; i++) |
... | ... | @@ -193,6 +225,7 @@ |
193 | 225 | static int lis3_12_rates[4] = {40, 160, 640, 2560}; |
194 | 226 | static int lis3_8_rates[2] = {100, 400}; |
195 | 227 | static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; |
228 | +static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; | |
196 | 229 | |
197 | 230 | /* ODR is Output Data Rate */ |
198 | 231 | static int lis3lv02d_get_odr(void) |
... | ... | @@ -253,7 +286,7 @@ |
253 | 286 | (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); |
254 | 287 | } |
255 | 288 | |
256 | - if (lis3_dev.whoami == WAI_3DC) { | |
289 | + if ((lis3_dev.whoami == WAI_3DC) || (lis3_dev.whoami == WAI_3DLH)) { | |
257 | 290 | ctlreg = CTRL_REG4; |
258 | 291 | selftest = CTRL4_ST0; |
259 | 292 | } else { |
... | ... | @@ -379,6 +412,8 @@ |
379 | 412 | lis3->read(lis3, CTRL_REG2, ®); |
380 | 413 | if (lis3->whoami == WAI_12B) |
381 | 414 | reg |= CTRL2_BDU | CTRL2_BOOT; |
415 | + else if (lis3->whoami == WAI_3DLH) | |
416 | + reg |= CTRL2_BOOT_3DLH; | |
382 | 417 | else |
383 | 418 | reg |= CTRL2_BOOT_8B; |
384 | 419 | lis3->write(lis3, CTRL_REG2, reg); |
... | ... | @@ -687,6 +722,36 @@ |
687 | 722 | } |
688 | 723 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); |
689 | 724 | |
725 | +static void lis3lv02d_update_g_range(struct lis3lv02d *lis3) | |
726 | +{ | |
727 | + u8 reg; | |
728 | + u8 val; | |
729 | + u8 shift; | |
730 | + | |
731 | + switch (lis3->g_range) { | |
732 | + case 8: | |
733 | + val = FS_8G_REGVAL; | |
734 | + shift = SHIFT_ADJ_8G; | |
735 | + lis3->scale = LIS3DLH_SENSITIVITY_8G; | |
736 | + break; | |
737 | + case 4: | |
738 | + val = FS_4G_REGVAL; | |
739 | + shift = SHIFT_ADJ_4G; | |
740 | + lis3->scale = LIS3DLH_SENSITIVITY_4G; | |
741 | + break; | |
742 | + case 2: | |
743 | + default: | |
744 | + val = FS_2G_REGVAL; | |
745 | + shift = SHIFT_ADJ_2G; | |
746 | + lis3->scale = LIS3DLH_SENSITIVITY_2G; | |
747 | + break; | |
748 | + } | |
749 | + | |
750 | + lis3->shift_adj = shift; | |
751 | + lis3->read(lis3, CTRL_REG4, ®); | |
752 | + lis3->write(lis3, CTRL_REG4, ((reg & ~FS_MASK) | val)); | |
753 | +} | |
754 | + | |
690 | 755 | /* Sysfs stuff */ |
691 | 756 | static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3) |
692 | 757 | { |
... | ... | @@ -751,6 +816,13 @@ |
751 | 816 | return sprintf(buf, "%d\n", lis3lv02d_get_odr()); |
752 | 817 | } |
753 | 818 | |
819 | +static ssize_t lis3lv02d_range_show(struct device *dev, | |
820 | + struct device_attribute *attr, char *buf) | |
821 | +{ | |
822 | + lis3lv02d_sysfs_poweron(&lis3_dev); | |
823 | + return sprintf(buf, "%d\n", lis3_dev.g_range); | |
824 | +} | |
825 | + | |
754 | 826 | static ssize_t lis3lv02d_rate_set(struct device *dev, |
755 | 827 | struct device_attribute *attr, const char *buf, |
756 | 828 | size_t count) |
757 | 829 | |
758 | 830 | |
... | ... | @@ -767,15 +839,33 @@ |
767 | 839 | return count; |
768 | 840 | } |
769 | 841 | |
842 | +static ssize_t lis3lv02d_range_set(struct device *dev, | |
843 | + struct device_attribute *attr, const char *buf, | |
844 | + size_t count) | |
845 | +{ | |
846 | + unsigned long range; | |
847 | + | |
848 | + if (strict_strtoul(buf, 0, &range)) | |
849 | + return -EINVAL; | |
850 | + | |
851 | + lis3_dev.g_range = range; | |
852 | + lis3lv02d_update_g_range(&lis3_dev); | |
853 | + | |
854 | + return count; | |
855 | +} | |
856 | + | |
770 | 857 | static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL); |
771 | 858 | static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); |
772 | 859 | static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show, |
773 | 860 | lis3lv02d_rate_set); |
861 | +static DEVICE_ATTR(range, S_IRUGO | S_IWUSR, lis3lv02d_range_show, | |
862 | + lis3lv02d_range_set); | |
774 | 863 | |
775 | 864 | static struct attribute *lis3lv02d_attributes[] = { |
776 | 865 | &dev_attr_selftest.attr, |
777 | 866 | &dev_attr_position.attr, |
778 | 867 | &dev_attr_rate.attr, |
868 | + &dev_attr_range.attr, | |
779 | 869 | NULL |
780 | 870 | }; |
781 | 871 | |
... | ... | @@ -910,6 +1000,19 @@ |
910 | 1000 | dev->odrs = lis3_3dc_rates; |
911 | 1001 | dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; |
912 | 1002 | dev->scale = LIS3_SENSITIVITY_8B; |
1003 | + break; | |
1004 | + case WAI_3DLH: | |
1005 | + pr_info("8 bits 3DLH sensor found\n"); | |
1006 | + dev->read_data = lis3lv02d_read_8; | |
1007 | + dev->mdps_max_val = 128; | |
1008 | + dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; | |
1009 | + dev->odrs = lis3_3dlh_rates; | |
1010 | + dev->odr_mask = CTRL1_DR0 | CTRL1_DR1; | |
1011 | + if (dev->pdata) { | |
1012 | + dev->g_range = dev->pdata->g_range; | |
1013 | + lis3lv02d_update_g_range(dev); | |
1014 | + } else | |
1015 | + dev->scale = LIS3DLH_SENSITIVITY_2G; | |
913 | 1016 | break; |
914 | 1017 | default: |
915 | 1018 | pr_err("unknown sensor type 0x%X\n", dev->whoami); |
drivers/misc/lis3lv02d/lis3lv02d.h
... | ... | @@ -94,13 +94,29 @@ |
94 | 94 | DD_THSE_H = 0x3F, |
95 | 95 | }; |
96 | 96 | |
97 | +enum lis331dlh_reg { | |
98 | + CTRL_REG5 = 0x24, | |
99 | + HP_FILTER_RESET_3DLH = 0x25, | |
100 | + REFERENCE = 0x26, | |
101 | +}; | |
102 | + | |
97 | 103 | enum lis3_who_am_i { |
104 | + WAI_3DLH = 0x32, /* 8 bits: LIS331DLH */ | |
98 | 105 | WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ |
99 | 106 | WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ |
100 | 107 | WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ |
101 | 108 | WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ |
102 | 109 | }; |
103 | 110 | |
111 | +enum lis3_type { | |
112 | + LIS3DC, | |
113 | + HP3DC, | |
114 | + LIS3LV02D, | |
115 | + LIS2302D, | |
116 | + LIS331DLF, | |
117 | + LIS331DLH, | |
118 | +}; | |
119 | + | |
104 | 120 | enum lis3lv02d_ctrl1_12b { |
105 | 121 | CTRL1_Xen = 0x01, |
106 | 122 | CTRL1_Yen = 0x02, |
... | ... | @@ -128,6 +144,32 @@ |
128 | 144 | CTRL1_ODR3 = 0x80, |
129 | 145 | }; |
130 | 146 | |
147 | +enum lis331dlh_ctrl1 { | |
148 | + CTRL1_DR0 = 0x08, | |
149 | + CTRL1_DR1 = 0x10, | |
150 | + CTRL1_PM0 = 0x20, | |
151 | + CTRL1_PM1 = 0x40, | |
152 | + CTRL1_PM2 = 0x80, | |
153 | +}; | |
154 | + | |
155 | +enum lis331dlh_ctrl2 { | |
156 | + CTRL2_HPEN1 = 0x04, | |
157 | + CTRL2_HPEN2 = 0x08, | |
158 | + CTRL2_FDS_3DLH = 0x10, | |
159 | + CTRL2_BOOT_3DLH = 0x80, | |
160 | +}; | |
161 | + | |
162 | +enum lis331dlh_ctrl4 { | |
163 | + CTRL4_STSIGN = 0x08, | |
164 | + CTRL4_BLE = 0x40, | |
165 | + CTRL4_BDU = 0x80, | |
166 | +}; | |
167 | + | |
168 | +enum lis331dlh_ctrl5 { | |
169 | + CTRL5_TURNON0 = 0x01, | |
170 | + CTRL5_TURNON1 = 0x20, | |
171 | +}; | |
172 | + | |
131 | 173 | enum lis3lv02d_ctrl2 { |
132 | 174 | CTRL2_DAS = 0x01, |
133 | 175 | CTRL2_SIM = 0x02, |
... | ... | @@ -147,6 +189,13 @@ |
147 | 189 | CTRL4_FS1 = 0x20, |
148 | 190 | }; |
149 | 191 | |
192 | +/* Measurement Range */ | |
193 | +enum lis3lv02d_fs { | |
194 | + FS_2G_REGVAL = 0x00, | |
195 | + FS_4G_REGVAL = 0x10, | |
196 | + FS_8G_REGVAL = 0x30, | |
197 | +}; | |
198 | + | |
150 | 199 | enum lis302d_ctrl2 { |
151 | 200 | HP_FF_WU2 = 0x08, |
152 | 201 | HP_FF_WU1 = 0x04, |
... | ... | @@ -184,6 +233,10 @@ |
184 | 233 | FF_WU_CFG_AOI = 0x80, |
185 | 234 | }; |
186 | 235 | |
236 | +enum lis331dlh_ff_wu_cfg { | |
237 | + FF_WU_CFG_6D = 0x40, | |
238 | +}; | |
239 | + | |
187 | 240 | enum lis3lv02d_ff_wu_src { |
188 | 241 | FF_WU_SRC_XL = 0x01, |
189 | 242 | FF_WU_SRC_XH = 0x02, |
... | ... | @@ -205,6 +258,10 @@ |
205 | 258 | DD_CFG_IEND = 0x80, |
206 | 259 | }; |
207 | 260 | |
261 | +enum lis331dlh_dd_cfg { | |
262 | + DD_CFG_6D = 0x40, | |
263 | +}; | |
264 | + | |
208 | 265 | enum lis3lv02d_dd_src { |
209 | 266 | DD_SRC_XL = 0x01, |
210 | 267 | DD_SRC_XH = 0x02, |
... | ... | @@ -279,6 +336,8 @@ |
279 | 336 | |
280 | 337 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ |
281 | 338 | struct mutex mutex; /* Serialize poll and selftest */ |
339 | + u8 g_range; /* Hold the g range */ | |
340 | + u8 shift_adj; | |
282 | 341 | }; |
283 | 342 | |
284 | 343 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
... | ... | @@ -91,7 +91,10 @@ |
91 | 91 | if (ret < 0) |
92 | 92 | return ret; |
93 | 93 | |
94 | - reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; | |
94 | + if (lis3->whoami == WAI_3DLH) | |
95 | + reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; | |
96 | + else | |
97 | + reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen; | |
95 | 98 | return lis3->write(lis3, CTRL_REG1, reg); |
96 | 99 | } |
97 | 100 | |
... | ... | @@ -237,6 +240,7 @@ |
237 | 240 | |
238 | 241 | static const struct i2c_device_id lis3lv02d_id[] = { |
239 | 242 | {"lis3lv02d", 0 }, |
243 | + {"lis331dlh", LIS331DLH}, | |
240 | 244 | {} |
241 | 245 | }; |
242 | 246 |
include/linux/lis3lv02d.h
... | ... | @@ -25,6 +25,7 @@ |
25 | 25 | * @axis_x: Sensor orientation remapping for x-axis |
26 | 26 | * @axis_y: Sensor orientation remapping for y-axis |
27 | 27 | * @axis_z: Sensor orientation remapping for z-axis |
28 | + * @g_range: Value contains the acceleration range, +/-2, +/-4 and +/-8 | |
28 | 29 | * @driver_features: Enable bits for different features. Disabled by default |
29 | 30 | * @default_rate: Default sampling rate. 0 means reset default |
30 | 31 | * @setup_resources: Interrupt line setup call back function |
... | ... | @@ -113,6 +114,7 @@ |
113 | 114 | s8 axis_x; |
114 | 115 | s8 axis_y; |
115 | 116 | s8 axis_z; |
117 | + u8 g_range; | |
116 | 118 | #define LIS3_USE_REGULATOR_CTRL 0x01 |
117 | 119 | #define LIS3_USE_BLOCK_READ 0x02 |
118 | 120 | u16 driver_features; |