Message ID | 2a93df6f99913e438dd2d394c074cf79544ab692.1659909060.git.jahau@rocketmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add support for magnetometer Yamaha YAS537 | expand |
On Mon, Aug 8, 2022 at 1:07 AM Jakob Hauser <jahau@rocketmail.com> wrote: > > Add temperature calculation to the "chip_info" structure to ease the handling > of different YAS variants. Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> > Signed-off-by: Jakob Hauser <jahau@rocketmail.com> > --- > drivers/iio/magnetometer/yamaha-yas530.c | 140 ++++++++++++----------- > 1 file changed, 71 insertions(+), 69 deletions(-) > > diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c > index 262a36c31616..780c7f4d1eff 100644 > --- a/drivers/iio/magnetometer/yamaha-yas530.c > +++ b/drivers/iio/magnetometer/yamaha-yas530.c > @@ -79,7 +79,6 @@ > #define YAS530_DATA_BITS 12 > #define YAS530_DATA_CENTER BIT(YAS530_DATA_BITS - 1) > #define YAS530_DATA_OVERFLOW (BIT(YAS530_DATA_BITS) - 1) > -#define YAS530_20DEGREES 182 /* Counts starting at -62 °C */ > > #define YAS532_DEVICE_ID 0x02 /* YAS532/YAS533 (MS-3R/F) */ > #define YAS532_VERSION_AB 0 /* YAS532/533 AB (MS-3R/F AB) */ > @@ -91,7 +90,6 @@ > #define YAS532_DATA_BITS 13 > #define YAS532_DATA_CENTER BIT(YAS532_DATA_BITS - 1) > #define YAS532_DATA_OVERFLOW (BIT(YAS532_DATA_BITS) - 1) > -#define YAS532_20DEGREES 390 /* Counts starting at -50 °C */ > > /* Turn off device regulators etc after 5 seconds of inactivity */ > #define YAS5XX_AUTOSUSPEND_DELAY_MS 5000 > @@ -119,6 +117,31 @@ static const int yas530_volatile_reg[] = { > YAS530_MEASURE, > }; > > +/* > + * t_ref_counts is the number of counts at reference temperature. > + * > + * The temperature value at YAS magnetometers is a number of counts. The > + * values in t_ref_counts[] are the counts at the reference temperature > + * of 20 °C. > + * > + * For YAS532/533, this value is known from the Android driver. For YAS530, > + * it was approximately measured. > + */ > +static const u16 t_ref_counts[] = { 182, 390, 390 }; > + > +/* > + * min_temp_celsius_x10 is the starting point of temperature counting > + * in 1/10:s degrees Celsius. > + * > + * The array min_temp_celsius_x10[] contains the temperatures where the > + * temperature value count is 0. The values are in 1/10:s degrees Celsius > + * to ease the further temperature calculation. > + * > + * These temperatures are derived from the temperature resolutions given > + * in the data sheets. > + */ > +static const s16 min_temp_celsius_x10[] = { -620, -500, -500 }; > + > struct yas5xx_calibration { > /* Linearization calibration x, y1, y2 */ > s32 r[3]; > @@ -143,6 +166,8 @@ struct yas5xx; > * @volatile_reg: device-specific volatile registers > * @volatile_reg_qty: quantity of device-specific volatile registers > * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE > + * @t_ref: number of counts at reference temperature > + * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius > */ > struct yas5xx_chip_info { > unsigned int devid; > @@ -151,6 +176,8 @@ struct yas5xx_chip_info { > const int *volatile_reg; > int volatile_reg_qty; > u32 scaling_val2; > + u16 t_ref; > + s16 min_temp_x10; > }; > > /** > @@ -349,6 +376,20 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis) > (yas5xx->hard_offsets[axis] - c->r[axis]) * coef; > } > > +static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t) > +{ > + s32 to; > + u16 t_ref; > + int min_temp_x10, ref_temp_x10; > + > + t_ref = yas5xx->chip_info->t_ref; > + min_temp_x10 = yas5xx->chip_info->min_temp_x10; > + ref_temp_x10 = 200; > + > + to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100; > + return to; > +} > + > /** > * yas530_get_measure() - Measure a sample of all axis and process > * @yas5xx: The device state > @@ -363,7 +404,7 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis) > static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo) > { > struct yas5xx_calibration *c = &yas5xx->calibration; > - u16 t_ref, t, x, y1, y2; > + u16 t_ref, t_comp, t, x, y1, y2; > /* These are signed x, signed y1 etc */ > s32 sx, sy1, sy2, sy, sz; > int ret; > @@ -378,47 +419,30 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, > sy1 = yas530_linearize(yas5xx, y1, 1); > sy2 = yas530_linearize(yas5xx, y2, 2); > > - /* Set the temperature reference value (unit: counts) */ > - switch (yas5xx->chip_info->devid) { > - case YAS530_DEVICE_ID: > - t_ref = YAS530_20DEGREES; > - break; > - case YAS532_DEVICE_ID: > - t_ref = YAS532_20DEGREES; > - break; > - default: > - dev_err(yas5xx->dev, "unknown device type\n"); > - return -EINVAL; > - } > - > - /* Temperature compensation for x, y1, y2 respectively */ > + /* > + * Set the temperature for compensation (unit: counts): > + * YAS532/YAS533 version AC uses the temperature deviation as a > + * multiplier. YAS530 and YAS532 version AB use solely the t value. > + */ > + t_ref = yas5xx->chip_info->t_ref; > if (yas5xx->chip_info->devid == YAS532_DEVICE_ID && > yas5xx->version == YAS532_VERSION_AC) { > - /* > - * YAS532 version AC uses the temperature deviation as a > - * multiplier. > - * > - * Cx * (t - t_ref) > - * x' = x - ---------------- > - * 100 > - */ > - sx = sx - (c->Cx * (t - t_ref)) / 100; > - sy1 = sy1 - (c->Cy1 * (t - t_ref)) / 100; > - sy2 = sy2 - (c->Cy2 * (t - t_ref)) / 100; > + t_comp = t - t_ref; > } else { > - /* > - * YAS530 and YAS532 version AB use solely the t value as a > - * multiplier. > - * > - * Cx * t > - * x' = x - ------ > - * 100 > - */ > - sx = sx - (c->Cx * t) / 100; > - sy1 = sy1 - (c->Cy1 * t) / 100; > - sy2 = sy2 - (c->Cy2 * t) / 100; > + t_comp = t; > } > > + /* > + * Temperature compensation for x, y1, y2 respectively: > + * > + * Cx * t_comp > + * x' = x - ----------- > + * 100 > + */ > + sx = sx - (c->Cx * t_comp) / 100; > + sy1 = sy1 - (c->Cy1 * t_comp) / 100; > + sy2 = sy2 - (c->Cy2 * t_comp) / 100; > + > /* > * Break y1 and y2 into y and z, y1 and y2 are apparently encoding > * y and z. > @@ -426,36 +450,8 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, > sy = sy1 - sy2; > sz = -sy1 - sy2; > > - /* Process temperature readout */ > - switch (yas5xx->chip_info->devid) { > - case YAS530_DEVICE_ID: > - /* > - * Raw temperature value t is the number of counts starting > - * at -62 °C. Reference value t_ref is the number of counts > - * between -62 °C and 20 °C (82 °C range). > - * > - * Temperature in °C would be (82 / t_ref * t) - 62. > - * > - * Contrary to this, perform multiplication first and division > - * second due to calculating with integers. > - * > - * To get a nicer result, calculate with 1/10:s degrees Celsius > - * and finally multiply by 100 to return millidegrees Celsius. > - */ > - *to = ((820 * t / t_ref) - 620) * 100; > - break; > - case YAS532_DEVICE_ID: > - /* > - * Actually same procedure for YAS532 but the starting point is > - * at -50 °C. Reference value t_ref is the number of counts > - * between -50 °C and 20 °C (70 °C range). > - */ > - *to = ((700 * t / t_ref) - 500) * 100; > - break; > - default: > - dev_err(yas5xx->dev, "unknown device type\n"); > - return -EINVAL; > - } > + /* Calculate temperature readout */ > + *to = yas5xx_calc_temperature(yas5xx, t); > > /* > * Calibrate [x,y,z] with some formulas like this: > @@ -943,6 +939,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { > .volatile_reg = yas530_volatile_reg, > .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), > .scaling_val2 = 100000000, /* picotesla to Gauss */ > + .t_ref = t_ref_counts[yas530], > + .min_temp_x10 = min_temp_celsius_x10[yas530], > }, > [yas532] = { > .devid = YAS532_DEVICE_ID, > @@ -951,6 +949,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { > .volatile_reg = yas530_volatile_reg, > .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), > .scaling_val2 = 100000, /* nanotesla to Gauss */ > + .t_ref = t_ref_counts[yas532], > + .min_temp_x10 = min_temp_celsius_x10[yas532], > }, > [yas533] = { > .devid = YAS532_DEVICE_ID, > @@ -959,6 +959,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { > .volatile_reg = yas530_volatile_reg, > .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), > .scaling_val2 = 100000, /* nanotesla to Gauss */ > + .t_ref = t_ref_counts[yas533], > + .min_temp_x10 = min_temp_celsius_x10[yas533], > }, > }; > > -- > 2.35.1 >
Hi Andy, On 08.08.22 13:36, Andy Shevchenko wrote: > On Mon, Aug 8, 2022 at 1:07 AM Jakob Hauser <jahau@rocketmail.com> wrote: >> >> Add temperature calculation to the "chip_info" structure to ease the handling >> of different YAS variants. > > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> ... Due to C11 standard 6.6.7 considering array calls not as constant expression (discussion on patch 9), the temperature values need to be moved directly into the chip_info table as well. I would move the comments in a reduced way into the kernel doc. It would look like this: /** * struct yas5xx_chip_info - device-specific data and function pointers ... * @t_ref: number of counts at reference temperature 20 °C * @min_temp_x10: starting point of temperature counting in 1/10:s * degrees Celsius ... * * The "t_ref" value for YAS532/533 is known from the Android driver. * For YAS530 it was approximately measured. * * The temperatures "min_temp_x10" are derived from the temperature * resolutions given in the data sheets. */ struct yas5xx_chip_info { ... u16 t_ref; s16 min_temp_x10; ... }; static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { [yas530] = { ... .t_ref = 182, /* counts */ .min_temp_x10 = -620, /* 1/10:s degrees Celsius */ ... }, [yas532] = { ... .t_ref = 390, /* counts */ .min_temp_x10 = -500, /* 1/10:s degrees Celsius */ ... }, [yas533] = { ... .t_ref = 390, /* counts */ .min_temp_x10 = -500, /* 1/10:s degrees Celsius */ ... }, }; As this is quite some change on that patch, I'd skip your "Reviewed-by:" tag and you would need to review it again in v6. Kind regards, Jakob
diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index 262a36c31616..780c7f4d1eff 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -79,7 +79,6 @@ #define YAS530_DATA_BITS 12 #define YAS530_DATA_CENTER BIT(YAS530_DATA_BITS - 1) #define YAS530_DATA_OVERFLOW (BIT(YAS530_DATA_BITS) - 1) -#define YAS530_20DEGREES 182 /* Counts starting at -62 °C */ #define YAS532_DEVICE_ID 0x02 /* YAS532/YAS533 (MS-3R/F) */ #define YAS532_VERSION_AB 0 /* YAS532/533 AB (MS-3R/F AB) */ @@ -91,7 +90,6 @@ #define YAS532_DATA_BITS 13 #define YAS532_DATA_CENTER BIT(YAS532_DATA_BITS - 1) #define YAS532_DATA_OVERFLOW (BIT(YAS532_DATA_BITS) - 1) -#define YAS532_20DEGREES 390 /* Counts starting at -50 °C */ /* Turn off device regulators etc after 5 seconds of inactivity */ #define YAS5XX_AUTOSUSPEND_DELAY_MS 5000 @@ -119,6 +117,31 @@ static const int yas530_volatile_reg[] = { YAS530_MEASURE, }; +/* + * t_ref_counts is the number of counts at reference temperature. + * + * The temperature value at YAS magnetometers is a number of counts. The + * values in t_ref_counts[] are the counts at the reference temperature + * of 20 °C. + * + * For YAS532/533, this value is known from the Android driver. For YAS530, + * it was approximately measured. + */ +static const u16 t_ref_counts[] = { 182, 390, 390 }; + +/* + * min_temp_celsius_x10 is the starting point of temperature counting + * in 1/10:s degrees Celsius. + * + * The array min_temp_celsius_x10[] contains the temperatures where the + * temperature value count is 0. The values are in 1/10:s degrees Celsius + * to ease the further temperature calculation. + * + * These temperatures are derived from the temperature resolutions given + * in the data sheets. + */ +static const s16 min_temp_celsius_x10[] = { -620, -500, -500 }; + struct yas5xx_calibration { /* Linearization calibration x, y1, y2 */ s32 r[3]; @@ -143,6 +166,8 @@ struct yas5xx; * @volatile_reg: device-specific volatile registers * @volatile_reg_qty: quantity of device-specific volatile registers * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE + * @t_ref: number of counts at reference temperature + * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius */ struct yas5xx_chip_info { unsigned int devid; @@ -151,6 +176,8 @@ struct yas5xx_chip_info { const int *volatile_reg; int volatile_reg_qty; u32 scaling_val2; + u16 t_ref; + s16 min_temp_x10; }; /** @@ -349,6 +376,20 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis) (yas5xx->hard_offsets[axis] - c->r[axis]) * coef; } +static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t) +{ + s32 to; + u16 t_ref; + int min_temp_x10, ref_temp_x10; + + t_ref = yas5xx->chip_info->t_ref; + min_temp_x10 = yas5xx->chip_info->min_temp_x10; + ref_temp_x10 = 200; + + to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100; + return to; +} + /** * yas530_get_measure() - Measure a sample of all axis and process * @yas5xx: The device state @@ -363,7 +404,7 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis) static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo) { struct yas5xx_calibration *c = &yas5xx->calibration; - u16 t_ref, t, x, y1, y2; + u16 t_ref, t_comp, t, x, y1, y2; /* These are signed x, signed y1 etc */ s32 sx, sy1, sy2, sy, sz; int ret; @@ -378,47 +419,30 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, sy1 = yas530_linearize(yas5xx, y1, 1); sy2 = yas530_linearize(yas5xx, y2, 2); - /* Set the temperature reference value (unit: counts) */ - switch (yas5xx->chip_info->devid) { - case YAS530_DEVICE_ID: - t_ref = YAS530_20DEGREES; - break; - case YAS532_DEVICE_ID: - t_ref = YAS532_20DEGREES; - break; - default: - dev_err(yas5xx->dev, "unknown device type\n"); - return -EINVAL; - } - - /* Temperature compensation for x, y1, y2 respectively */ + /* + * Set the temperature for compensation (unit: counts): + * YAS532/YAS533 version AC uses the temperature deviation as a + * multiplier. YAS530 and YAS532 version AB use solely the t value. + */ + t_ref = yas5xx->chip_info->t_ref; if (yas5xx->chip_info->devid == YAS532_DEVICE_ID && yas5xx->version == YAS532_VERSION_AC) { - /* - * YAS532 version AC uses the temperature deviation as a - * multiplier. - * - * Cx * (t - t_ref) - * x' = x - ---------------- - * 100 - */ - sx = sx - (c->Cx * (t - t_ref)) / 100; - sy1 = sy1 - (c->Cy1 * (t - t_ref)) / 100; - sy2 = sy2 - (c->Cy2 * (t - t_ref)) / 100; + t_comp = t - t_ref; } else { - /* - * YAS530 and YAS532 version AB use solely the t value as a - * multiplier. - * - * Cx * t - * x' = x - ------ - * 100 - */ - sx = sx - (c->Cx * t) / 100; - sy1 = sy1 - (c->Cy1 * t) / 100; - sy2 = sy2 - (c->Cy2 * t) / 100; + t_comp = t; } + /* + * Temperature compensation for x, y1, y2 respectively: + * + * Cx * t_comp + * x' = x - ----------- + * 100 + */ + sx = sx - (c->Cx * t_comp) / 100; + sy1 = sy1 - (c->Cy1 * t_comp) / 100; + sy2 = sy2 - (c->Cy2 * t_comp) / 100; + /* * Break y1 and y2 into y and z, y1 and y2 are apparently encoding * y and z. @@ -426,36 +450,8 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, sy = sy1 - sy2; sz = -sy1 - sy2; - /* Process temperature readout */ - switch (yas5xx->chip_info->devid) { - case YAS530_DEVICE_ID: - /* - * Raw temperature value t is the number of counts starting - * at -62 °C. Reference value t_ref is the number of counts - * between -62 °C and 20 °C (82 °C range). - * - * Temperature in °C would be (82 / t_ref * t) - 62. - * - * Contrary to this, perform multiplication first and division - * second due to calculating with integers. - * - * To get a nicer result, calculate with 1/10:s degrees Celsius - * and finally multiply by 100 to return millidegrees Celsius. - */ - *to = ((820 * t / t_ref) - 620) * 100; - break; - case YAS532_DEVICE_ID: - /* - * Actually same procedure for YAS532 but the starting point is - * at -50 °C. Reference value t_ref is the number of counts - * between -50 °C and 20 °C (70 °C range). - */ - *to = ((700 * t / t_ref) - 500) * 100; - break; - default: - dev_err(yas5xx->dev, "unknown device type\n"); - return -EINVAL; - } + /* Calculate temperature readout */ + *to = yas5xx_calc_temperature(yas5xx, t); /* * Calibrate [x,y,z] with some formulas like this: @@ -943,6 +939,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { .volatile_reg = yas530_volatile_reg, .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), .scaling_val2 = 100000000, /* picotesla to Gauss */ + .t_ref = t_ref_counts[yas530], + .min_temp_x10 = min_temp_celsius_x10[yas530], }, [yas532] = { .devid = YAS532_DEVICE_ID, @@ -951,6 +949,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { .volatile_reg = yas530_volatile_reg, .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), .scaling_val2 = 100000, /* nanotesla to Gauss */ + .t_ref = t_ref_counts[yas532], + .min_temp_x10 = min_temp_celsius_x10[yas532], }, [yas533] = { .devid = YAS532_DEVICE_ID, @@ -959,6 +959,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { .volatile_reg = yas530_volatile_reg, .volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), .scaling_val2 = 100000, /* nanotesla to Gauss */ + .t_ref = t_ref_counts[yas533], + .min_temp_x10 = min_temp_celsius_x10[yas533], }, };
Add temperature calculation to the "chip_info" structure to ease the handling of different YAS variants. Signed-off-by: Jakob Hauser <jahau@rocketmail.com> --- drivers/iio/magnetometer/yamaha-yas530.c | 140 ++++++++++++----------- 1 file changed, 71 insertions(+), 69 deletions(-)