Skip to content

Commit 2d6676e

Browse files
Jakko3jic23
authored andcommitted
iio: magnetometer: yas530: Add temperature calculation to "chip_info"
Add temperature calculation to the "chip_info" structure to ease the handling of different YAS variants. Signed-off-by: Jakob Hauser <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Link: https://lore.kernel.org/r/1a8bffdb7e807455620a73f2d61981e7f9aab8d5.1660337264.git.jahau@rocketmail.com Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 913fd40 commit 2d6676e

File tree

1 file changed

+54
-69
lines changed

1 file changed

+54
-69
lines changed

drivers/iio/magnetometer/yamaha-yas530.c

Lines changed: 54 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
#define YAS530_DATA_BITS 12
8080
#define YAS530_DATA_CENTER BIT(YAS530_DATA_BITS - 1)
8181
#define YAS530_DATA_OVERFLOW (BIT(YAS530_DATA_BITS) - 1)
82-
#define YAS530_20DEGREES 182 /* Counts starting at -62 °C */
8382

8483
#define YAS532_DEVICE_ID 0x02 /* YAS532/YAS533 (MS-3R/F) */
8584
#define YAS532_VERSION_AB 0 /* YAS532/533 AB (MS-3R/F AB) */
@@ -91,7 +90,6 @@
9190
#define YAS532_DATA_BITS 13
9291
#define YAS532_DATA_CENTER BIT(YAS532_DATA_BITS - 1)
9392
#define YAS532_DATA_OVERFLOW (BIT(YAS532_DATA_BITS) - 1)
94-
#define YAS532_20DEGREES 390 /* Counts starting at -50 °C */
9593

9694
/* Turn off device regulators etc after 5 seconds of inactivity */
9795
#define YAS5XX_AUTOSUSPEND_DELAY_MS 5000
@@ -131,6 +129,14 @@ struct yas5xx;
131129
* @volatile_reg: device-specific volatile registers
132130
* @volatile_reg_qty: quantity of device-specific volatile registers
133131
* @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE
132+
* @t_ref: number of counts at reference temperature 20 °C
133+
* @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius
134+
*
135+
* The "t_ref" value for YAS532/533 is known from the Android driver.
136+
* For YAS530 it was approximately measured.
137+
*
138+
* The temperatures "min_temp_x10" are derived from the temperature resolutions
139+
* given in the data sheets.
134140
*/
135141
struct yas5xx_chip_info {
136142
unsigned int devid;
@@ -139,6 +145,8 @@ struct yas5xx_chip_info {
139145
const int *volatile_reg;
140146
int volatile_reg_qty;
141147
u32 scaling_val2;
148+
u16 t_ref;
149+
s16 min_temp_x10;
142150
};
143151

144152
/**
@@ -337,6 +345,22 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis)
337345
(yas5xx->hard_offsets[axis] - c->r[axis]) * coef;
338346
}
339347

348+
static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t)
349+
{
350+
const struct yas5xx_chip_info *ci = yas5xx->chip_info;
351+
s32 to;
352+
u16 t_ref;
353+
s16 min_temp_x10;
354+
int ref_temp_x10;
355+
356+
t_ref = ci->t_ref;
357+
min_temp_x10 = ci->min_temp_x10;
358+
ref_temp_x10 = 200;
359+
360+
to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100;
361+
return to;
362+
}
363+
340364
/**
341365
* yas530_get_measure() - Measure a sample of all axis and process
342366
* @yas5xx: The device state
@@ -352,7 +376,7 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo,
352376
{
353377
const struct yas5xx_chip_info *ci = yas5xx->chip_info;
354378
struct yas5xx_calibration *c = &yas5xx->calibration;
355-
u16 t_ref, t, x, y1, y2;
379+
u16 t_ref, t_comp, t, x, y1, y2;
356380
/* These are signed x, signed y1 etc */
357381
s32 sx, sy1, sy2, sy, sz;
358382
int ret;
@@ -367,84 +391,39 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo,
367391
sy1 = yas530_linearize(yas5xx, y1, 1);
368392
sy2 = yas530_linearize(yas5xx, y2, 2);
369393

370-
/* Set the temperature reference value (unit: counts) */
371-
switch (ci->devid) {
372-
case YAS530_DEVICE_ID:
373-
t_ref = YAS530_20DEGREES;
374-
break;
375-
case YAS532_DEVICE_ID:
376-
t_ref = YAS532_20DEGREES;
377-
break;
378-
default:
379-
dev_err(yas5xx->dev, "unknown device type\n");
380-
return -EINVAL;
381-
}
382-
383-
/* Temperature compensation for x, y1, y2 respectively */
394+
/*
395+
* Set the temperature for compensation (unit: counts):
396+
* YAS532/YAS533 version AC uses the temperature deviation as a
397+
* multiplier. YAS530 and YAS532 version AB use solely the t value.
398+
*/
399+
t_ref = ci->t_ref;
384400
if (ci->devid == YAS532_DEVICE_ID &&
385401
yas5xx->version == YAS532_VERSION_AC) {
386-
/*
387-
* YAS532 version AC uses the temperature deviation as a
388-
* multiplier.
389-
*
390-
* Cx * (t - t_ref)
391-
* x' = x - ----------------
392-
* 100
393-
*/
394-
sx = sx - (c->Cx * (t - t_ref)) / 100;
395-
sy1 = sy1 - (c->Cy1 * (t - t_ref)) / 100;
396-
sy2 = sy2 - (c->Cy2 * (t - t_ref)) / 100;
402+
t_comp = t - t_ref;
397403
} else {
398-
/*
399-
* YAS530 and YAS532 version AB use solely the t value as a
400-
* multiplier.
401-
*
402-
* Cx * t
403-
* x' = x - ------
404-
* 100
405-
*/
406-
sx = sx - (c->Cx * t) / 100;
407-
sy1 = sy1 - (c->Cy1 * t) / 100;
408-
sy2 = sy2 - (c->Cy2 * t) / 100;
404+
t_comp = t;
409405
}
410406

407+
/*
408+
* Temperature compensation for x, y1, y2 respectively:
409+
*
410+
* Cx * t_comp
411+
* x' = x - -----------
412+
* 100
413+
*/
414+
sx = sx - (c->Cx * t_comp) / 100;
415+
sy1 = sy1 - (c->Cy1 * t_comp) / 100;
416+
sy2 = sy2 - (c->Cy2 * t_comp) / 100;
417+
411418
/*
412419
* Break y1 and y2 into y and z, y1 and y2 are apparently encoding
413420
* y and z.
414421
*/
415422
sy = sy1 - sy2;
416423
sz = -sy1 - sy2;
417424

418-
/* Process temperature readout */
419-
switch (ci->devid) {
420-
case YAS530_DEVICE_ID:
421-
/*
422-
* Raw temperature value t is the number of counts starting
423-
* at -62 °C. Reference value t_ref is the number of counts
424-
* between -62 °C and 20 °C (82 °C range).
425-
*
426-
* Temperature in °C would be (82 / t_ref * t) - 62.
427-
*
428-
* Contrary to this, perform multiplication first and division
429-
* second due to calculating with integers.
430-
*
431-
* To get a nicer result, calculate with 1/10:s degrees Celsius
432-
* and finally multiply by 100 to return millidegrees Celsius.
433-
*/
434-
*to = ((820 * t / t_ref) - 620) * 100;
435-
break;
436-
case YAS532_DEVICE_ID:
437-
/*
438-
* Actually same procedure for YAS532 but the starting point is
439-
* at -50 °C. Reference value t_ref is the number of counts
440-
* between -50 °C and 20 °C (70 °C range).
441-
*/
442-
*to = ((700 * t / t_ref) - 500) * 100;
443-
break;
444-
default:
445-
dev_err(yas5xx->dev, "unknown device type\n");
446-
return -EINVAL;
447-
}
425+
/* Calculate temperature readout */
426+
*to = yas5xx_calc_temperature(yas5xx, t);
448427

449428
/*
450429
* Calibrate [x,y,z] with some formulas like this:
@@ -935,6 +914,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = {
935914
.volatile_reg = yas530_volatile_reg,
936915
.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
937916
.scaling_val2 = 100000000, /* picotesla to Gauss */
917+
.t_ref = 182, /* counts */
918+
.min_temp_x10 = -620, /* 1/10:s degrees Celsius */
938919
},
939920
[yas532] = {
940921
.devid = YAS532_DEVICE_ID,
@@ -943,6 +924,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = {
943924
.volatile_reg = yas530_volatile_reg,
944925
.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
945926
.scaling_val2 = 100000, /* nanotesla to Gauss */
927+
.t_ref = 390, /* counts */
928+
.min_temp_x10 = -500, /* 1/10:s degrees Celsius */
946929
},
947930
[yas533] = {
948931
.devid = YAS532_DEVICE_ID,
@@ -951,6 +934,8 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = {
951934
.volatile_reg = yas530_volatile_reg,
952935
.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
953936
.scaling_val2 = 100000, /* nanotesla to Gauss */
937+
.t_ref = 390, /* counts */
938+
.min_temp_x10 = -500, /* 1/10:s degrees Celsius */
954939
},
955940
};
956941

0 commit comments

Comments
 (0)