diff options
author | Vlad Dogaru <vlad.dogaru@intel.com> | 2014-11-20 07:00:48 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-12-12 07:28:25 -0500 |
commit | 0f8994b18afc47fd0cda20ba6162c21a093173da (patch) | |
tree | b21f92ddcaf147786b5e57ac9437d229c1a292bf /drivers/iio | |
parent | 8f6eb02596cc297c12ee16c86b9bbe1c186dda15 (diff) |
iio: bmp280: refactor compensation code
This version of the code avoids extra memory copy operations and is
somewhat smaller in code size.
Signed-off-by: Vlad Dogaru <vlad.dogaru@intel.com>
Acked-by: Hartmut Knaack <knaack.h@gmx.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/pressure/bmp280.c | 140 |
1 files changed, 52 insertions, 88 deletions
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 75038dacfff1..47dfd347f66f 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c | |||
@@ -80,16 +80,12 @@ struct bmp280_data { | |||
80 | s32 t_fine; | 80 | s32 t_fine; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* Compensation parameters. */ | 83 | /* |
84 | struct bmp280_comp_temp { | 84 | * These enums are used for indexing into the array of compensation |
85 | u16 dig_t1; | 85 | * parameters. |
86 | s16 dig_t2, dig_t3; | 86 | */ |
87 | }; | 87 | enum { T1, T2, T3 }; |
88 | 88 | enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; | |
89 | struct bmp280_comp_press { | ||
90 | u16 dig_p1; | ||
91 | s16 dig_p2, dig_p3, dig_p4, dig_p5, dig_p6, dig_p7, dig_p8, dig_p9; | ||
92 | }; | ||
93 | 89 | ||
94 | static const struct iio_chan_spec bmp280_channels[] = { | 90 | static const struct iio_chan_spec bmp280_channels[] = { |
95 | { | 91 | { |
@@ -141,54 +137,6 @@ static const struct regmap_config bmp280_regmap_config = { | |||
141 | .volatile_reg = bmp280_is_volatile_reg, | 137 | .volatile_reg = bmp280_is_volatile_reg, |
142 | }; | 138 | }; |
143 | 139 | ||
144 | static int bmp280_read_compensation_temp(struct bmp280_data *data, | ||
145 | struct bmp280_comp_temp *comp) | ||
146 | { | ||
147 | int ret; | ||
148 | __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; | ||
149 | |||
150 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, | ||
151 | buf, BMP280_COMP_TEMP_REG_COUNT); | ||
152 | if (ret < 0) { | ||
153 | dev_err(&data->client->dev, | ||
154 | "failed to read temperature calibration parameters\n"); | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | comp->dig_t1 = (u16) le16_to_cpu(buf[0]); | ||
159 | comp->dig_t2 = (s16) le16_to_cpu(buf[1]); | ||
160 | comp->dig_t3 = (s16) le16_to_cpu(buf[2]); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int bmp280_read_compensation_press(struct bmp280_data *data, | ||
166 | struct bmp280_comp_press *comp) | ||
167 | { | ||
168 | int ret; | ||
169 | __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; | ||
170 | |||
171 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, | ||
172 | buf, BMP280_COMP_PRESS_REG_COUNT); | ||
173 | if (ret < 0) { | ||
174 | dev_err(&data->client->dev, | ||
175 | "failed to read pressure calibration parameters\n"); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | comp->dig_p1 = (u16) le16_to_cpu(buf[0]); | ||
180 | comp->dig_p2 = (s16) le16_to_cpu(buf[1]); | ||
181 | comp->dig_p3 = (s16) le16_to_cpu(buf[2]); | ||
182 | comp->dig_p4 = (s16) le16_to_cpu(buf[3]); | ||
183 | comp->dig_p5 = (s16) le16_to_cpu(buf[4]); | ||
184 | comp->dig_p6 = (s16) le16_to_cpu(buf[5]); | ||
185 | comp->dig_p7 = (s16) le16_to_cpu(buf[6]); | ||
186 | comp->dig_p8 = (s16) le16_to_cpu(buf[7]); | ||
187 | comp->dig_p9 = (s16) le16_to_cpu(buf[8]); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* | 140 | /* |
193 | * Returns temperature in DegC, resolution is 0.01 DegC. Output value of | 141 | * Returns temperature in DegC, resolution is 0.01 DegC. Output value of |
194 | * "5123" equals 51.23 DegC. t_fine carries fine temperature as global | 142 | * "5123" equals 51.23 DegC. t_fine carries fine temperature as global |
@@ -197,16 +145,33 @@ static int bmp280_read_compensation_press(struct bmp280_data *data, | |||
197 | * Taken from datasheet, Section 3.11.3, "Compensation formula". | 145 | * Taken from datasheet, Section 3.11.3, "Compensation formula". |
198 | */ | 146 | */ |
199 | static s32 bmp280_compensate_temp(struct bmp280_data *data, | 147 | static s32 bmp280_compensate_temp(struct bmp280_data *data, |
200 | struct bmp280_comp_temp *comp, | ||
201 | s32 adc_temp) | 148 | s32 adc_temp) |
202 | { | 149 | { |
150 | int ret; | ||
203 | s32 var1, var2, t; | 151 | s32 var1, var2, t; |
152 | __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; | ||
153 | |||
154 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, | ||
155 | buf, BMP280_COMP_TEMP_REG_COUNT); | ||
156 | if (ret < 0) { | ||
157 | dev_err(&data->client->dev, | ||
158 | "failed to read temperature calibration parameters\n"); | ||
159 | return ret; | ||
160 | } | ||
204 | 161 | ||
205 | var1 = (((adc_temp >> 3) - ((s32) comp->dig_t1 << 1)) * | 162 | /* |
206 | ((s32) comp->dig_t2)) >> 11; | 163 | * The double casts are necessary because le16_to_cpu returns an |
207 | var2 = (((((adc_temp >> 4) - ((s32) comp->dig_t1)) * | 164 | * unsigned 16-bit value. Casting that value directly to a |
208 | ((adc_temp >> 4) - ((s32) comp->dig_t1))) >> 12) * | 165 | * signed 32-bit will not do proper sign extension. |
209 | ((s32) comp->dig_t3)) >> 14; | 166 | * |
167 | * Conversely, T1 and P1 are unsigned values, so they can be | ||
168 | * cast straight to the larger type. | ||
169 | */ | ||
170 | var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) * | ||
171 | ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11; | ||
172 | var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) * | ||
173 | ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) * | ||
174 | ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14; | ||
210 | 175 | ||
211 | data->t_fine = var1 + var2; | 176 | data->t_fine = var1 + var2; |
212 | t = (data->t_fine * 5 + 128) >> 8; | 177 | t = (data->t_fine * 5 + 128) >> 8; |
@@ -222,27 +187,36 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, | |||
222 | * Taken from datasheet, Section 3.11.3, "Compensation formula". | 187 | * Taken from datasheet, Section 3.11.3, "Compensation formula". |
223 | */ | 188 | */ |
224 | static u32 bmp280_compensate_press(struct bmp280_data *data, | 189 | static u32 bmp280_compensate_press(struct bmp280_data *data, |
225 | struct bmp280_comp_press *comp, | ||
226 | s32 adc_press) | 190 | s32 adc_press) |
227 | { | 191 | { |
192 | int ret; | ||
228 | s64 var1, var2, p; | 193 | s64 var1, var2, p; |
194 | __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; | ||
195 | |||
196 | ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, | ||
197 | buf, BMP280_COMP_PRESS_REG_COUNT); | ||
198 | if (ret < 0) { | ||
199 | dev_err(&data->client->dev, | ||
200 | "failed to read pressure calibration parameters\n"); | ||
201 | return ret; | ||
202 | } | ||
229 | 203 | ||
230 | var1 = ((s64) data->t_fine) - 128000; | 204 | var1 = ((s64)data->t_fine) - 128000; |
231 | var2 = var1 * var1 * (s64) comp->dig_p6; | 205 | var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]); |
232 | var2 = var2 + ((var1 * (s64) comp->dig_p5) << 17); | 206 | var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17); |
233 | var2 = var2 + (((s64) comp->dig_p4) << 35); | 207 | var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35); |
234 | var1 = ((var1 * var1 * (s64) comp->dig_p3) >> 8) + | 208 | var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) + |
235 | ((var1 * (s64) comp->dig_p2) << 12); | 209 | ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12); |
236 | var1 = (((((s64) 1) << 47) + var1)) * ((s64) comp->dig_p1) >> 33; | 210 | var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33; |
237 | 211 | ||
238 | if (var1 == 0) | 212 | if (var1 == 0) |
239 | return 0; | 213 | return 0; |
240 | 214 | ||
241 | p = ((((s64) 1048576 - adc_press) << 31) - var2) * 3125; | 215 | p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125; |
242 | p = div64_s64(p, var1); | 216 | p = div64_s64(p, var1); |
243 | var1 = (((s64) comp->dig_p9) * (p >> 13) * (p >> 13)) >> 25; | 217 | var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25; |
244 | var2 = (((s64) comp->dig_p8) * p) >> 19; | 218 | var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19; |
245 | p = ((p + var1 + var2) >> 8) + (((s64) comp->dig_p7) << 4); | 219 | p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4); |
246 | 220 | ||
247 | return (u32) p; | 221 | return (u32) p; |
248 | } | 222 | } |
@@ -253,11 +227,6 @@ static int bmp280_read_temp(struct bmp280_data *data, | |||
253 | int ret; | 227 | int ret; |
254 | __be32 tmp = 0; | 228 | __be32 tmp = 0; |
255 | s32 adc_temp, comp_temp; | 229 | s32 adc_temp, comp_temp; |
256 | struct bmp280_comp_temp comp; | ||
257 | |||
258 | ret = bmp280_read_compensation_temp(data, &comp); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | 230 | ||
262 | ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, | 231 | ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, |
263 | (u8 *) &tmp, 3); | 232 | (u8 *) &tmp, 3); |
@@ -267,7 +236,7 @@ static int bmp280_read_temp(struct bmp280_data *data, | |||
267 | } | 236 | } |
268 | 237 | ||
269 | adc_temp = be32_to_cpu(tmp) >> 12; | 238 | adc_temp = be32_to_cpu(tmp) >> 12; |
270 | comp_temp = bmp280_compensate_temp(data, &comp, adc_temp); | 239 | comp_temp = bmp280_compensate_temp(data, adc_temp); |
271 | 240 | ||
272 | /* | 241 | /* |
273 | * val might be NULL if we're called by the read_press routine, | 242 | * val might be NULL if we're called by the read_press routine, |
@@ -288,11 +257,6 @@ static int bmp280_read_press(struct bmp280_data *data, | |||
288 | __be32 tmp = 0; | 257 | __be32 tmp = 0; |
289 | s32 adc_press; | 258 | s32 adc_press; |
290 | u32 comp_press; | 259 | u32 comp_press; |
291 | struct bmp280_comp_press comp; | ||
292 | |||
293 | ret = bmp280_read_compensation_press(data, &comp); | ||
294 | if (ret < 0) | ||
295 | return ret; | ||
296 | 260 | ||
297 | /* Read and compensate temperature so we get a reading of t_fine. */ | 261 | /* Read and compensate temperature so we get a reading of t_fine. */ |
298 | ret = bmp280_read_temp(data, NULL); | 262 | ret = bmp280_read_temp(data, NULL); |
@@ -307,7 +271,7 @@ static int bmp280_read_press(struct bmp280_data *data, | |||
307 | } | 271 | } |
308 | 272 | ||
309 | adc_press = be32_to_cpu(tmp) >> 12; | 273 | adc_press = be32_to_cpu(tmp) >> 12; |
310 | comp_press = bmp280_compensate_press(data, &comp, adc_press); | 274 | comp_press = bmp280_compensate_press(data, adc_press); |
311 | 275 | ||
312 | *val = comp_press; | 276 | *val = comp_press; |
313 | *val2 = 256000; | 277 | *val2 = 256000; |