Commit 0f8994b1 authored by Vlad Dogaru's avatar Vlad Dogaru Committed by Jonathan Cameron

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: default avatarVlad Dogaru <vlad.dogaru@intel.com>
Acked-by: default avatarHartmut Knaack <knaack.h@gmx.de>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 8f6eb025
...@@ -80,16 +80,12 @@ struct bmp280_data { ...@@ -80,16 +80,12 @@ struct bmp280_data {
s32 t_fine; s32 t_fine;
}; };
/* Compensation parameters. */ /*
struct bmp280_comp_temp { * These enums are used for indexing into the array of compensation
u16 dig_t1; * parameters.
s16 dig_t2, dig_t3; */
}; enum { T1, T2, T3 };
enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
struct bmp280_comp_press {
u16 dig_p1;
s16 dig_p2, dig_p3, dig_p4, dig_p5, dig_p6, dig_p7, dig_p8, dig_p9;
};
static const struct iio_chan_spec bmp280_channels[] = { static const struct iio_chan_spec bmp280_channels[] = {
{ {
...@@ -141,10 +137,18 @@ static const struct regmap_config bmp280_regmap_config = { ...@@ -141,10 +137,18 @@ static const struct regmap_config bmp280_regmap_config = {
.volatile_reg = bmp280_is_volatile_reg, .volatile_reg = bmp280_is_volatile_reg,
}; };
static int bmp280_read_compensation_temp(struct bmp280_data *data, /*
struct bmp280_comp_temp *comp) * Returns temperature in DegC, resolution is 0.01 DegC. Output value of
* "5123" equals 51.23 DegC. t_fine carries fine temperature as global
* value.
*
* Taken from datasheet, Section 3.11.3, "Compensation formula".
*/
static s32 bmp280_compensate_temp(struct bmp280_data *data,
s32 adc_temp)
{ {
int ret; int ret;
s32 var1, var2, t;
__le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2];
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
...@@ -155,58 +159,19 @@ static int bmp280_read_compensation_temp(struct bmp280_data *data, ...@@ -155,58 +159,19 @@ static int bmp280_read_compensation_temp(struct bmp280_data *data,
return ret; return ret;
} }
comp->dig_t1 = (u16) le16_to_cpu(buf[0]); /*
comp->dig_t2 = (s16) le16_to_cpu(buf[1]); * The double casts are necessary because le16_to_cpu returns an
comp->dig_t3 = (s16) le16_to_cpu(buf[2]); * unsigned 16-bit value. Casting that value directly to a
* signed 32-bit will not do proper sign extension.
return 0;
}
static int bmp280_read_compensation_press(struct bmp280_data *data,
struct bmp280_comp_press *comp)
{
int ret;
__le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2];
ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
buf, BMP280_COMP_PRESS_REG_COUNT);
if (ret < 0) {
dev_err(&data->client->dev,
"failed to read pressure calibration parameters\n");
return ret;
}
comp->dig_p1 = (u16) le16_to_cpu(buf[0]);
comp->dig_p2 = (s16) le16_to_cpu(buf[1]);
comp->dig_p3 = (s16) le16_to_cpu(buf[2]);
comp->dig_p4 = (s16) le16_to_cpu(buf[3]);
comp->dig_p5 = (s16) le16_to_cpu(buf[4]);
comp->dig_p6 = (s16) le16_to_cpu(buf[5]);
comp->dig_p7 = (s16) le16_to_cpu(buf[6]);
comp->dig_p8 = (s16) le16_to_cpu(buf[7]);
comp->dig_p9 = (s16) le16_to_cpu(buf[8]);
return 0;
}
/*
* Returns temperature in DegC, resolution is 0.01 DegC. Output value of
* "5123" equals 51.23 DegC. t_fine carries fine temperature as global
* value.
* *
* Taken from datasheet, Section 3.11.3, "Compensation formula". * Conversely, T1 and P1 are unsigned values, so they can be
* cast straight to the larger type.
*/ */
static s32 bmp280_compensate_temp(struct bmp280_data *data, var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) *
struct bmp280_comp_temp *comp, ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11;
s32 adc_temp) var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) *
{ ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) *
s32 var1, var2, t; ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14;
var1 = (((adc_temp >> 3) - ((s32) comp->dig_t1 << 1)) *
((s32) comp->dig_t2)) >> 11;
var2 = (((((adc_temp >> 4) - ((s32) comp->dig_t1)) *
((adc_temp >> 4) - ((s32) comp->dig_t1))) >> 12) *
((s32) comp->dig_t3)) >> 14;
data->t_fine = var1 + var2; data->t_fine = var1 + var2;
t = (data->t_fine * 5 + 128) >> 8; t = (data->t_fine * 5 + 128) >> 8;
...@@ -222,27 +187,36 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, ...@@ -222,27 +187,36 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
* Taken from datasheet, Section 3.11.3, "Compensation formula". * Taken from datasheet, Section 3.11.3, "Compensation formula".
*/ */
static u32 bmp280_compensate_press(struct bmp280_data *data, static u32 bmp280_compensate_press(struct bmp280_data *data,
struct bmp280_comp_press *comp,
s32 adc_press) s32 adc_press)
{ {
int ret;
s64 var1, var2, p; s64 var1, var2, p;
__le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2];
var1 = ((s64) data->t_fine) - 128000; ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
var2 = var1 * var1 * (s64) comp->dig_p6; buf, BMP280_COMP_PRESS_REG_COUNT);
var2 = var2 + ((var1 * (s64) comp->dig_p5) << 17); if (ret < 0) {
var2 = var2 + (((s64) comp->dig_p4) << 35); dev_err(&data->client->dev,
var1 = ((var1 * var1 * (s64) comp->dig_p3) >> 8) + "failed to read pressure calibration parameters\n");
((var1 * (s64) comp->dig_p2) << 12); return ret;
var1 = (((((s64) 1) << 47) + var1)) * ((s64) comp->dig_p1) >> 33; }
var1 = ((s64)data->t_fine) - 128000;
var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]);
var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17);
var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35);
var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) +
((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12);
var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33;
if (var1 == 0) if (var1 == 0)
return 0; return 0;
p = ((((s64) 1048576 - adc_press) << 31) - var2) * 3125; p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125;
p = div64_s64(p, var1); p = div64_s64(p, var1);
var1 = (((s64) comp->dig_p9) * (p >> 13) * (p >> 13)) >> 25; var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((s64) comp->dig_p8) * p) >> 19; var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((s64) comp->dig_p7) << 4); p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4);
return (u32) p; return (u32) p;
} }
...@@ -253,11 +227,6 @@ static int bmp280_read_temp(struct bmp280_data *data, ...@@ -253,11 +227,6 @@ static int bmp280_read_temp(struct bmp280_data *data,
int ret; int ret;
__be32 tmp = 0; __be32 tmp = 0;
s32 adc_temp, comp_temp; s32 adc_temp, comp_temp;
struct bmp280_comp_temp comp;
ret = bmp280_read_compensation_temp(data, &comp);
if (ret < 0)
return ret;
ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
(u8 *) &tmp, 3); (u8 *) &tmp, 3);
...@@ -267,7 +236,7 @@ static int bmp280_read_temp(struct bmp280_data *data, ...@@ -267,7 +236,7 @@ static int bmp280_read_temp(struct bmp280_data *data,
} }
adc_temp = be32_to_cpu(tmp) >> 12; adc_temp = be32_to_cpu(tmp) >> 12;
comp_temp = bmp280_compensate_temp(data, &comp, adc_temp); comp_temp = bmp280_compensate_temp(data, adc_temp);
/* /*
* val might be NULL if we're called by the read_press routine, * 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,11 +257,6 @@ static int bmp280_read_press(struct bmp280_data *data,
__be32 tmp = 0; __be32 tmp = 0;
s32 adc_press; s32 adc_press;
u32 comp_press; u32 comp_press;
struct bmp280_comp_press comp;
ret = bmp280_read_compensation_press(data, &comp);
if (ret < 0)
return ret;
/* Read and compensate temperature so we get a reading of t_fine. */ /* Read and compensate temperature so we get a reading of t_fine. */
ret = bmp280_read_temp(data, NULL); ret = bmp280_read_temp(data, NULL);
...@@ -307,7 +271,7 @@ static int bmp280_read_press(struct bmp280_data *data, ...@@ -307,7 +271,7 @@ static int bmp280_read_press(struct bmp280_data *data,
} }
adc_press = be32_to_cpu(tmp) >> 12; adc_press = be32_to_cpu(tmp) >> 12;
comp_press = bmp280_compensate_press(data, &comp, adc_press); comp_press = bmp280_compensate_press(data, adc_press);
*val = comp_press; *val = comp_press;
*val2 = 256000; *val2 = 256000;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment