Skip to content

Commit cb372b4

Browse files
DimitriFedraujic23
authored andcommitted
iio: humditiy: hdc3020: fix units for thresholds and hysteresis
According to the ABI the units after application of scale and offset are milli degree celsius for temperature thresholds and milli percent for relative humidity thresholds. Currently the resulting units are degree celsius for temperature thresholds and hysteresis and percent for relative humidity thresholds and hysteresis. Change scale factor to fix this issue. Fixes: 3ad0e7e ("iio: humidity: hdc3020: add threshold events support") Reported-by: Chris Lesiak <chris.lesiak@licorbio.com> Reviewed-by: Javier Carrasco <javier.carrasco.cruz@gmail.com> Signed-off-by: Dimitri Fedrau <dimitri.fedrau@liebherr.com> Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 7b8dc11 commit cb372b4

1 file changed

Lines changed: 41 additions & 28 deletions

File tree

drivers/iio/humidity/hdc3020.c

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@
7272
#define HDC3020_MAX_TEMP_HYST_MICRO 164748607
7373
#define HDC3020_MAX_HUM_MICRO 99220264
7474

75+
/* Divide 65535 from the datasheet by 5 to avoid overflows */
76+
#define HDC3020_THRESH_FRACTION (65535 / 5)
77+
7578
struct hdc3020_data {
7679
struct i2c_client *client;
7780
struct gpio_desc *reset_gpio;
@@ -376,15 +379,18 @@ static int hdc3020_thresh_get_temp(u16 thresh)
376379
int temp;
377380

378381
/*
379-
* Get the temperature threshold from 9 LSBs, shift them to get
380-
* the truncated temperature threshold representation and
381-
* calculate the threshold according to the formula in the
382-
* datasheet. Result is degree celsius scaled by 65535.
382+
* Get the temperature threshold from 9 LSBs, shift them to get the
383+
* truncated temperature threshold representation and calculate the
384+
* threshold according to the explicit formula in the datasheet:
385+
* T(C) = -45 + (175 * temp) / 65535.
386+
* Additionally scale by HDC3020_THRESH_FRACTION to avoid precision loss
387+
* when calculating threshold and hysteresis values. Result is degree
388+
* celsius scaled by HDC3020_THRESH_FRACTION.
383389
*/
384390
temp = FIELD_GET(HDC3020_THRESH_TEMP_MASK, thresh) <<
385391
HDC3020_THRESH_TEMP_TRUNC_SHIFT;
386392

387-
return -2949075 + (175 * temp);
393+
return -2949075 / 5 + (175 / 5 * temp);
388394
}
389395

390396
static int hdc3020_thresh_get_hum(u16 thresh)
@@ -394,13 +400,16 @@ static int hdc3020_thresh_get_hum(u16 thresh)
394400
/*
395401
* Get the humidity threshold from 7 MSBs, shift them to get the
396402
* truncated humidity threshold representation and calculate the
397-
* threshold according to the formula in the datasheet. Result is
398-
* percent scaled by 65535.
403+
* threshold according to the explicit formula in the datasheet:
404+
* RH(%) = 100 * hum / 65535.
405+
* Additionally scale by HDC3020_THRESH_FRACTION to avoid precision loss
406+
* when calculating threshold and hysteresis values. Result is percent
407+
* scaled by HDC3020_THRESH_FRACTION.
399408
*/
400409
hum = FIELD_GET(HDC3020_THRESH_HUM_MASK, thresh) <<
401410
HDC3020_THRESH_HUM_TRUNC_SHIFT;
402411

403-
return hum * 100;
412+
return hum * 100 / 5;
404413
}
405414

406415
static u16 hdc3020_thresh_set_temp(int s_temp, u16 curr_thresh)
@@ -455,8 +464,8 @@ int hdc3020_thresh_clr(s64 s_thresh, s64 s_hyst, enum iio_event_direction dir)
455464
else
456465
s_clr = s_thresh + s_hyst;
457466

458-
/* Divide by 65535 to get units of micro */
459-
return div_s64(s_clr, 65535);
467+
/* Divide by HDC3020_THRESH_FRACTION to get units of micro */
468+
return div_s64(s_clr, HDC3020_THRESH_FRACTION);
460469
}
461470

462471
static int _hdc3020_write_thresh(struct hdc3020_data *data, u16 reg, u16 val)
@@ -507,7 +516,7 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
507516

508517
clr = ret;
509518
/* Scale value to include decimal part into calculations */
510-
s_val = (val < 0) ? (val * 1000000 - val2) : (val * 1000000 + val2);
519+
s_val = (val < 0) ? (val * 1000 - val2) : (val * 1000 + val2);
511520
switch (chan->type) {
512521
case IIO_TEMP:
513522
switch (info) {
@@ -523,7 +532,8 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
523532
/* Calculate old hysteresis */
524533
s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000;
525534
s_clr = (s64)hdc3020_thresh_get_temp(clr) * 1000000;
526-
s_hyst = div_s64(abs(s_thresh - s_clr), 65535);
535+
s_hyst = div_s64(abs(s_thresh - s_clr),
536+
HDC3020_THRESH_FRACTION);
527537
/* Set new threshold */
528538
thresh = reg_val;
529539
/* Set old hysteresis */
@@ -532,16 +542,17 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
532542
case IIO_EV_INFO_HYSTERESIS:
533543
/*
534544
* Function hdc3020_thresh_get_temp returns temperature
535-
* in degree celsius scaled by 65535. Scale by 1000000
536-
* to be able to subtract scaled hysteresis value.
545+
* in degree celsius scaled by HDC3020_THRESH_FRACTION.
546+
* Scale by 1000000 to be able to subtract scaled
547+
* hysteresis value.
537548
*/
538549
s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000;
539550
/*
540551
* Units of s_val are in micro degree celsius, scale by
541-
* 65535 to get same units as s_thresh.
552+
* HDC3020_THRESH_FRACTION to get same units as s_thresh.
542553
*/
543554
s_val = min(abs(s_val), HDC3020_MAX_TEMP_HYST_MICRO);
544-
s_hyst = (s64)s_val * 65535;
555+
s_hyst = (s64)s_val * HDC3020_THRESH_FRACTION;
545556
s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir);
546557
s_clr = max(s_clr, HDC3020_MIN_TEMP_MICRO);
547558
s_clr = min(s_clr, HDC3020_MAX_TEMP_MICRO);
@@ -565,7 +576,8 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
565576
/* Calculate old hysteresis */
566577
s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000;
567578
s_clr = (s64)hdc3020_thresh_get_hum(clr) * 1000000;
568-
s_hyst = div_s64(abs(s_thresh - s_clr), 65535);
579+
s_hyst = div_s64(abs(s_thresh - s_clr),
580+
HDC3020_THRESH_FRACTION);
569581
/* Set new threshold */
570582
thresh = reg_val;
571583
/* Try to set old hysteresis */
@@ -574,15 +586,16 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
574586
case IIO_EV_INFO_HYSTERESIS:
575587
/*
576588
* Function hdc3020_thresh_get_hum returns relative
577-
* humidity in percent scaled by 65535. Scale by 1000000
578-
* to be able to subtract scaled hysteresis value.
589+
* humidity in percent scaled by HDC3020_THRESH_FRACTION.
590+
* Scale by 1000000 to be able to subtract scaled
591+
* hysteresis value.
579592
*/
580593
s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000;
581594
/*
582-
* Units of s_val are in micro percent, scale by 65535
583-
* to get same units as s_thresh.
595+
* Units of s_val are in micro percent, scale by
596+
* HDC3020_THRESH_FRACTION to get same units as s_thresh.
584597
*/
585-
s_hyst = (s64)s_val * 65535;
598+
s_hyst = (s64)s_val * HDC3020_THRESH_FRACTION;
586599
s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir);
587600
s_clr = max(s_clr, 0);
588601
s_clr = min(s_clr, HDC3020_MAX_HUM_MICRO);
@@ -630,39 +643,39 @@ static int hdc3020_read_thresh(struct iio_dev *indio_dev,
630643
thresh = hdc3020_thresh_get_temp(ret);
631644
switch (info) {
632645
case IIO_EV_INFO_VALUE:
633-
*val = thresh;
646+
*val = thresh * MILLI;
634647
break;
635648
case IIO_EV_INFO_HYSTERESIS:
636649
ret = hdc3020_read_be16(data, reg_clr);
637650
if (ret < 0)
638651
return ret;
639652

640653
clr = hdc3020_thresh_get_temp(ret);
641-
*val = abs(thresh - clr);
654+
*val = abs(thresh - clr) * MILLI;
642655
break;
643656
default:
644657
return -EOPNOTSUPP;
645658
}
646-
*val2 = 65535;
659+
*val2 = HDC3020_THRESH_FRACTION;
647660
return IIO_VAL_FRACTIONAL;
648661
case IIO_HUMIDITYRELATIVE:
649662
thresh = hdc3020_thresh_get_hum(ret);
650663
switch (info) {
651664
case IIO_EV_INFO_VALUE:
652-
*val = thresh;
665+
*val = thresh * MILLI;
653666
break;
654667
case IIO_EV_INFO_HYSTERESIS:
655668
ret = hdc3020_read_be16(data, reg_clr);
656669
if (ret < 0)
657670
return ret;
658671

659672
clr = hdc3020_thresh_get_hum(ret);
660-
*val = abs(thresh - clr);
673+
*val = abs(thresh - clr) * MILLI;
661674
break;
662675
default:
663676
return -EOPNOTSUPP;
664677
}
665-
*val2 = 65535;
678+
*val2 = HDC3020_THRESH_FRACTION;
666679
return IIO_VAL_FRACTIONAL;
667680
default:
668681
return -EOPNOTSUPP;

0 commit comments

Comments
 (0)