Merge tag 'iio-fixes-for-6.10b' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-linus

Jonathan writes:

IIO: 2nd set of fixes for 6.10

The usual mixed bag of new stuff and long term issues that have surfaced
as a particular driver gets more adoption.

adi,ad7266
- Add missing error check that could lead to bad data being reported.
adi,ad9739a
- Fix Kconfig to not allow COMPILE_TEST to override lack SPI support.
bosch,bme680
- Fix units for pressure value (off by factor of 10)
- Fix sign on a calibration variable read back from the device
- Avoid integer overflow in compensation functions.
- Fix an issue with read sequence that leads to stale data and bad first
reading.
freescale,fxls8962af
- Kconfig dependency fixes.
ti,hdc3020
- Fix representation of hysteresis to match ABI by being an offset from
the current event threshold, not an absolute value.
xilinx,ams
- Don't include the ams_ctrl_channels in a computed mask. This driver is
making an unusual use of scan_mask (it doesn't support buffers) and that
lead to an overflow.

* tag 'iio-fixes-for-6.10b' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
iio: chemical: bme680: Fix sensor data read operation
iio: chemical: bme680: Fix overflows in compensate() functions
iio: chemical: bme680: Fix calibration data variable
iio: chemical: bme680: Fix pressure value output
iio: humidity: hdc3020: fix hysteresis representation
iio: dac: fix ad9739a random config compile error
iio: accel: fxls8962af: select IIO_BUFFER & IIO_KFIFO_BUF
iio: adc: ad7266: Fix variable checking bug
iio: xilinx-ams: Don't include ams_ctrl_channels in scan_mask

+315 -86
+2
drivers/iio/accel/Kconfig
··· 330 config FXLS8962AF 331 tristate 332 depends on I2C || !I2C # cannot be built-in for modular I2C 333 334 config FXLS8962AF_I2C 335 tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver"
··· 330 config FXLS8962AF 331 tristate 332 depends on I2C || !I2C # cannot be built-in for modular I2C 333 + select IIO_BUFFER 334 + select IIO_KFIFO_BUF 335 336 config FXLS8962AF_I2C 337 tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver"
+2
drivers/iio/adc/ad7266.c
··· 157 ret = ad7266_read_single(st, val, chan->address); 158 iio_device_release_direct_mode(indio_dev); 159 160 *val = (*val >> 2) & 0xfff; 161 if (chan->scan_type.sign == 's') 162 *val = sign_extend32(*val,
··· 157 ret = ad7266_read_single(st, val, chan->address); 158 iio_device_release_direct_mode(indio_dev); 159 160 + if (ret < 0) 161 + return ret; 162 *val = (*val >> 2) & 0xfff; 163 if (chan->scan_type.sign == 's') 164 *val = sign_extend32(*val,
+6 -2
drivers/iio/adc/xilinx-ams.c
··· 414 415 /* Run calibration of PS & PL as part of the sequence */ 416 scan_mask = BIT(0) | BIT(AMS_PS_SEQ_MAX); 417 - for (i = 0; i < indio_dev->num_channels; i++) 418 - scan_mask |= BIT_ULL(indio_dev->channels[i].scan_index); 419 420 if (ams->ps_base) { 421 /* put sysmon in a soft reset to change the sequence */
··· 414 415 /* Run calibration of PS & PL as part of the sequence */ 416 scan_mask = BIT(0) | BIT(AMS_PS_SEQ_MAX); 417 + for (i = 0; i < indio_dev->num_channels; i++) { 418 + const struct iio_chan_spec *chan = &indio_dev->channels[i]; 419 + 420 + if (chan->scan_index < AMS_CTRL_SEQ_BASE) 421 + scan_mask |= BIT_ULL(chan->scan_index); 422 + } 423 424 if (ams->ps_base) { 425 /* put sysmon in a soft reset to change the sequence */
+2
drivers/iio/chemical/bme680.h
··· 54 #define BME680_NB_CONV_MASK GENMASK(3, 0) 55 56 #define BME680_REG_MEAS_STAT_0 0x1D 57 #define BME680_GAS_MEAS_BIT BIT(6) 58 59 /* Calibration Parameters */ 60 #define BME680_T2_LSB_REG 0x8A
··· 54 #define BME680_NB_CONV_MASK GENMASK(3, 0) 55 56 #define BME680_REG_MEAS_STAT_0 0x1D 57 + #define BME680_NEW_DATA_BIT BIT(7) 58 #define BME680_GAS_MEAS_BIT BIT(6) 59 + #define BME680_MEAS_BIT BIT(5) 60 61 /* Calibration Parameters */ 62 #define BME680_T2_LSB_REG 0x8A
+54 -8
drivers/iio/chemical/bme680_core.c
··· 10 */ 11 #include <linux/acpi.h> 12 #include <linux/bitfield.h> 13 #include <linux/device.h> 14 #include <linux/module.h> 15 #include <linux/log2.h> ··· 39 s8 par_h3; 40 s8 par_h4; 41 s8 par_h5; 42 - s8 par_h6; 43 s8 par_h7; 44 s8 par_gh1; 45 s16 par_gh2; ··· 343 if (!calib->par_t2) 344 bme680_read_calib(data, calib); 345 346 - var1 = (adc_temp >> 3) - (calib->par_t1 << 1); 347 var2 = (var1 * calib->par_t2) >> 11; 348 var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; 349 - var3 = (var3 * (calib->par_t3 << 4)) >> 14; 350 data->t_fine = var2 + var3; 351 calc_temp = (data->t_fine * 5 + 128) >> 8; 352 ··· 369 var1 = (data->t_fine >> 1) - 64000; 370 var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2; 371 var2 = var2 + (var1 * calib->par_p5 << 1); 372 - var2 = (var2 >> 2) + (calib->par_p4 << 16); 373 var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * 374 - (calib->par_p3 << 5)) >> 3) + 375 ((calib->par_p2 * var1) >> 1); 376 var1 = var1 >> 18; 377 var1 = ((32768 + var1) * calib->par_p1) >> 15; ··· 389 var3 = ((press_comp >> 8) * (press_comp >> 8) * 390 (press_comp >> 8) * calib->par_p10) >> 17; 391 392 - press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4; 393 394 return press_comp; 395 } ··· 415 (((temp_scaled * ((temp_scaled * calib->par_h5) / 100)) 416 >> 6) / 100) + (1 << 14))) >> 10; 417 var3 = var1 * var2; 418 - var4 = calib->par_h6 << 7; 419 var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4; 420 var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; 421 var6 = (var4 * var5) >> 1; ··· 533 return ilog2(val) + 1; 534 } 535 536 static int bme680_chip_config(struct bme680_data *data) 537 { 538 struct device *dev = regmap_get_device(data->regmap); ··· 660 if (ret < 0) 661 return ret; 662 663 ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB, 664 &tmp, 3); 665 if (ret < 0) { ··· 720 } 721 722 *val = bme680_compensate_press(data, adc_press); 723 - *val2 = 100; 724 return IIO_VAL_FRACTIONAL; 725 } 726 ··· 778 /* set forced mode to trigger measurement */ 779 ret = bme680_set_mode(data, true); 780 if (ret < 0) 781 return ret; 782 783 ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
··· 10 */ 11 #include <linux/acpi.h> 12 #include <linux/bitfield.h> 13 + #include <linux/delay.h> 14 #include <linux/device.h> 15 #include <linux/module.h> 16 #include <linux/log2.h> ··· 38 s8 par_h3; 39 s8 par_h4; 40 s8 par_h5; 41 + u8 par_h6; 42 s8 par_h7; 43 s8 par_gh1; 44 s16 par_gh2; ··· 342 if (!calib->par_t2) 343 bme680_read_calib(data, calib); 344 345 + var1 = (adc_temp >> 3) - ((s32)calib->par_t1 << 1); 346 var2 = (var1 * calib->par_t2) >> 11; 347 var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; 348 + var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14; 349 data->t_fine = var2 + var3; 350 calc_temp = (data->t_fine * 5 + 128) >> 8; 351 ··· 368 var1 = (data->t_fine >> 1) - 64000; 369 var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2; 370 var2 = var2 + (var1 * calib->par_p5 << 1); 371 + var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16); 372 var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * 373 + ((s32)calib->par_p3 << 5)) >> 3) + 374 ((calib->par_p2 * var1) >> 1); 375 var1 = var1 >> 18; 376 var1 = ((32768 + var1) * calib->par_p1) >> 15; ··· 388 var3 = ((press_comp >> 8) * (press_comp >> 8) * 389 (press_comp >> 8) * calib->par_p10) >> 17; 390 391 + press_comp += (var1 + var2 + var3 + ((s32)calib->par_p7 << 7)) >> 4; 392 393 return press_comp; 394 } ··· 414 (((temp_scaled * ((temp_scaled * calib->par_h5) / 100)) 415 >> 6) / 100) + (1 << 14))) >> 10; 416 var3 = var1 * var2; 417 + var4 = (s32)calib->par_h6 << 7; 418 var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4; 419 var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; 420 var6 = (var4 * var5) >> 1; ··· 532 return ilog2(val) + 1; 533 } 534 535 + /* 536 + * Taken from Bosch BME680 API: 537 + * https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L490 538 + */ 539 + static int bme680_wait_for_eoc(struct bme680_data *data) 540 + { 541 + struct device *dev = regmap_get_device(data->regmap); 542 + unsigned int check; 543 + int ret; 544 + /* 545 + * (Sum of oversampling ratios * time per oversampling) + 546 + * TPH measurement + gas measurement + wait transition from forced mode 547 + * + heater duration 548 + */ 549 + int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press + 550 + data->oversampling_humid) * 1936) + (477 * 4) + 551 + (477 * 5) + 1000 + (data->heater_dur * 1000); 552 + 553 + usleep_range(wait_eoc_us, wait_eoc_us + 100); 554 + 555 + ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check); 556 + if (ret) { 557 + dev_err(dev, "failed to read measurement status register.\n"); 558 + return ret; 559 + } 560 + if (check & BME680_MEAS_BIT) { 561 + dev_err(dev, "Device measurement cycle incomplete.\n"); 562 + return -EBUSY; 563 + } 564 + if (!(check & BME680_NEW_DATA_BIT)) { 565 + dev_err(dev, "No new data available from the device.\n"); 566 + return -ENODATA; 567 + } 568 + 569 + return 0; 570 + } 571 + 572 static int bme680_chip_config(struct bme680_data *data) 573 { 574 struct device *dev = regmap_get_device(data->regmap); ··· 622 if (ret < 0) 623 return ret; 624 625 + ret = bme680_wait_for_eoc(data); 626 + if (ret) 627 + return ret; 628 + 629 ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB, 630 &tmp, 3); 631 if (ret < 0) { ··· 678 } 679 680 *val = bme680_compensate_press(data, adc_press); 681 + *val2 = 1000; 682 return IIO_VAL_FRACTIONAL; 683 } 684 ··· 736 /* set forced mode to trigger measurement */ 737 ret = bme680_set_mode(data, true); 738 if (ret < 0) 739 + return ret; 740 + 741 + ret = bme680_wait_for_eoc(data); 742 + if (ret) 743 return ret; 744 745 ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
+1 -1
drivers/iio/dac/Kconfig
··· 133 134 config AD9739A 135 tristate "Analog Devices AD9739A RF DAC spi driver" 136 - depends on SPI || COMPILE_TEST 137 select REGMAP_SPI 138 select IIO_BACKEND 139 help
··· 133 134 config AD9739A 135 tristate "Analog Devices AD9739A RF DAC spi driver" 136 + depends on SPI 137 select REGMAP_SPI 138 select IIO_BACKEND 139 help
+248 -75
drivers/iio/humidity/hdc3020.c
··· 19 #include <linux/i2c.h> 20 #include <linux/init.h> 21 #include <linux/interrupt.h> 22 #include <linux/module.h> 23 #include <linux/mutex.h> 24 #include <linux/pm.h> ··· 67 68 #define HDC3020_CRC8_POLYNOMIAL 0x31 69 70 - #define HDC3020_MIN_TEMP -40 71 - #define HDC3020_MAX_TEMP 125 72 73 struct hdc3020_data { 74 struct i2c_client *client; ··· 371 return -EINVAL; 372 } 373 374 static int hdc3020_write_thresh(struct iio_dev *indio_dev, 375 const struct iio_chan_spec *chan, 376 enum iio_event_type type, ··· 478 int val, int val2) 479 { 480 struct hdc3020_data *data = iio_priv(indio_dev); 481 - u8 buf[5]; 482 - u64 tmp; 483 - u16 reg; 484 - int ret; 485 486 - /* Supported temperature range is from –40 to 125 degree celsius */ 487 - if (val < HDC3020_MIN_TEMP || val > HDC3020_MAX_TEMP) 488 - return -EINVAL; 489 - 490 - /* Select threshold register */ 491 - if (info == IIO_EV_INFO_VALUE) { 492 - if (dir == IIO_EV_DIR_RISING) 493 - reg = HDC3020_S_T_RH_THRESH_HIGH; 494 - else 495 - reg = HDC3020_S_T_RH_THRESH_LOW; 496 } else { 497 - if (dir == IIO_EV_DIR_RISING) 498 - reg = HDC3020_S_T_RH_THRESH_HIGH_CLR; 499 - else 500 - reg = HDC3020_S_T_RH_THRESH_LOW_CLR; 501 } 502 503 guard(mutex)(&data->lock); 504 - ret = hdc3020_read_be16(data, reg); 505 if (ret < 0) 506 return ret; 507 508 switch (chan->type) { 509 case IIO_TEMP: 510 - /* 511 - * Calculate temperature threshold, shift it down to get the 512 - * truncated threshold representation in the 9LSBs while keeping 513 - * the current humidity threshold in the 7 MSBs. 514 - */ 515 - tmp = ((u64)(((val + 45) * MICRO) + val2)) * 65535ULL; 516 - tmp = div_u64(tmp, MICRO * 175); 517 - val = tmp >> HDC3020_THRESH_TEMP_TRUNC_SHIFT; 518 - val = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, val); 519 - val |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, ret) << 520 - HDC3020_THRESH_HUM_TRUNC_SHIFT); 521 break; 522 case IIO_HUMIDITYRELATIVE: 523 - /* 524 - * Calculate humidity threshold, shift it down and up to get the 525 - * truncated threshold representation in the 7MSBs while keeping 526 - * the current temperature threshold in the 9 LSBs. 527 - */ 528 - tmp = ((u64)((val * MICRO) + val2)) * 65535ULL; 529 - tmp = div_u64(tmp, MICRO * 100); 530 - val = tmp >> HDC3020_THRESH_HUM_TRUNC_SHIFT; 531 - val = FIELD_PREP(HDC3020_THRESH_HUM_MASK, val); 532 - val |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret); 533 break; 534 default: 535 return -EOPNOTSUPP; 536 } 537 538 - put_unaligned_be16(reg, buf); 539 - put_unaligned_be16(val, buf + 2); 540 - buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE); 541 - return hdc3020_write_bytes(data, buf, 5); 542 } 543 544 static int hdc3020_read_thresh(struct iio_dev *indio_dev, ··· 608 int *val, int *val2) 609 { 610 struct hdc3020_data *data = iio_priv(indio_dev); 611 - u16 reg; 612 - int ret; 613 614 - /* Select threshold register */ 615 - if (info == IIO_EV_INFO_VALUE) { 616 - if (dir == IIO_EV_DIR_RISING) 617 - reg = HDC3020_R_T_RH_THRESH_HIGH; 618 - else 619 - reg = HDC3020_R_T_RH_THRESH_LOW; 620 } else { 621 - if (dir == IIO_EV_DIR_RISING) 622 - reg = HDC3020_R_T_RH_THRESH_HIGH_CLR; 623 - else 624 - reg = HDC3020_R_T_RH_THRESH_LOW_CLR; 625 } 626 627 guard(mutex)(&data->lock); 628 - ret = hdc3020_read_be16(data, reg); 629 if (ret < 0) 630 return ret; 631 632 switch (chan->type) { 633 case IIO_TEMP: 634 - /* 635 - * Get the temperature threshold from 9 LSBs, shift them to get 636 - * the truncated temperature threshold representation and 637 - * calculate the threshold according to the formula in the 638 - * datasheet. 639 - */ 640 - *val = FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret); 641 - *val = *val << HDC3020_THRESH_TEMP_TRUNC_SHIFT; 642 - *val = -2949075 + (175 * (*val)); 643 *val2 = 65535; 644 return IIO_VAL_FRACTIONAL; 645 case IIO_HUMIDITYRELATIVE: 646 - /* 647 - * Get the humidity threshold from 7 MSBs, shift them to get the 648 - * truncated humidity threshold representation and calculate the 649 - * threshold according to the formula in the datasheet. 650 - */ 651 - *val = FIELD_GET(HDC3020_THRESH_HUM_MASK, ret); 652 - *val = (*val << HDC3020_THRESH_HUM_TRUNC_SHIFT) * 100; 653 *val2 = 65535; 654 return IIO_VAL_FRACTIONAL; 655 default:
··· 19 #include <linux/i2c.h> 20 #include <linux/init.h> 21 #include <linux/interrupt.h> 22 + #include <linux/math64.h> 23 #include <linux/module.h> 24 #include <linux/mutex.h> 25 #include <linux/pm.h> ··· 66 67 #define HDC3020_CRC8_POLYNOMIAL 0x31 68 69 + #define HDC3020_MIN_TEMP_MICRO -39872968 70 + #define HDC3020_MAX_TEMP_MICRO 124875639 71 + #define HDC3020_MAX_TEMP_HYST_MICRO 164748607 72 + #define HDC3020_MAX_HUM_MICRO 99220264 73 74 struct hdc3020_data { 75 struct i2c_client *client; ··· 368 return -EINVAL; 369 } 370 371 + static int hdc3020_thresh_get_temp(u16 thresh) 372 + { 373 + int temp; 374 + 375 + /* 376 + * Get the temperature threshold from 9 LSBs, shift them to get 377 + * the truncated temperature threshold representation and 378 + * calculate the threshold according to the formula in the 379 + * datasheet. Result is degree celsius scaled by 65535. 380 + */ 381 + temp = FIELD_GET(HDC3020_THRESH_TEMP_MASK, thresh) << 382 + HDC3020_THRESH_TEMP_TRUNC_SHIFT; 383 + 384 + return -2949075 + (175 * temp); 385 + } 386 + 387 + static int hdc3020_thresh_get_hum(u16 thresh) 388 + { 389 + int hum; 390 + 391 + /* 392 + * Get the humidity threshold from 7 MSBs, shift them to get the 393 + * truncated humidity threshold representation and calculate the 394 + * threshold according to the formula in the datasheet. Result is 395 + * percent scaled by 65535. 396 + */ 397 + hum = FIELD_GET(HDC3020_THRESH_HUM_MASK, thresh) << 398 + HDC3020_THRESH_HUM_TRUNC_SHIFT; 399 + 400 + return hum * 100; 401 + } 402 + 403 + static u16 hdc3020_thresh_set_temp(int s_temp, u16 curr_thresh) 404 + { 405 + u64 temp; 406 + u16 thresh; 407 + 408 + /* 409 + * Calculate temperature threshold, shift it down to get the 410 + * truncated threshold representation in the 9LSBs while keeping 411 + * the current humidity threshold in the 7 MSBs. 412 + */ 413 + temp = (u64)(s_temp + 45000000) * 65535ULL; 414 + temp = div_u64(temp, 1000000 * 175) >> HDC3020_THRESH_TEMP_TRUNC_SHIFT; 415 + thresh = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, temp); 416 + thresh |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, curr_thresh) << 417 + HDC3020_THRESH_HUM_TRUNC_SHIFT); 418 + 419 + return thresh; 420 + } 421 + 422 + static u16 hdc3020_thresh_set_hum(int s_hum, u16 curr_thresh) 423 + { 424 + u64 hum; 425 + u16 thresh; 426 + 427 + /* 428 + * Calculate humidity threshold, shift it down and up to get the 429 + * truncated threshold representation in the 7MSBs while keeping 430 + * the current temperature threshold in the 9 LSBs. 431 + */ 432 + hum = (u64)(s_hum) * 65535ULL; 433 + hum = div_u64(hum, 1000000 * 100) >> HDC3020_THRESH_HUM_TRUNC_SHIFT; 434 + thresh = FIELD_PREP(HDC3020_THRESH_HUM_MASK, hum); 435 + thresh |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, curr_thresh); 436 + 437 + return thresh; 438 + } 439 + 440 + static 441 + int hdc3020_thresh_clr(s64 s_thresh, s64 s_hyst, enum iio_event_direction dir) 442 + { 443 + s64 s_clr; 444 + 445 + /* 446 + * Include directions when calculation the clear value, 447 + * since hysteresis is unsigned by definition and the 448 + * clear value is an absolute value which is signed. 449 + */ 450 + if (dir == IIO_EV_DIR_RISING) 451 + s_clr = s_thresh - s_hyst; 452 + else 453 + s_clr = s_thresh + s_hyst; 454 + 455 + /* Divide by 65535 to get units of micro */ 456 + return div_s64(s_clr, 65535); 457 + } 458 + 459 + static int _hdc3020_write_thresh(struct hdc3020_data *data, u16 reg, u16 val) 460 + { 461 + u8 buf[5]; 462 + 463 + put_unaligned_be16(reg, buf); 464 + put_unaligned_be16(val, buf + 2); 465 + buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE); 466 + 467 + return hdc3020_write_bytes(data, buf, 5); 468 + } 469 + 470 static int hdc3020_write_thresh(struct iio_dev *indio_dev, 471 const struct iio_chan_spec *chan, 472 enum iio_event_type type, ··· 376 int val, int val2) 377 { 378 struct hdc3020_data *data = iio_priv(indio_dev); 379 + u16 reg, reg_val, reg_thresh_rd, reg_clr_rd, reg_thresh_wr, reg_clr_wr; 380 + s64 s_thresh, s_hyst, s_clr; 381 + int s_val, thresh, clr, ret; 382 383 + /* Select threshold registers */ 384 + if (dir == IIO_EV_DIR_RISING) { 385 + reg_thresh_rd = HDC3020_R_T_RH_THRESH_HIGH; 386 + reg_thresh_wr = HDC3020_S_T_RH_THRESH_HIGH; 387 + reg_clr_rd = HDC3020_R_T_RH_THRESH_HIGH_CLR; 388 + reg_clr_wr = HDC3020_S_T_RH_THRESH_HIGH_CLR; 389 } else { 390 + reg_thresh_rd = HDC3020_R_T_RH_THRESH_LOW; 391 + reg_thresh_wr = HDC3020_S_T_RH_THRESH_LOW; 392 + reg_clr_rd = HDC3020_R_T_RH_THRESH_LOW_CLR; 393 + reg_clr_wr = HDC3020_S_T_RH_THRESH_LOW_CLR; 394 } 395 396 guard(mutex)(&data->lock); 397 + ret = hdc3020_read_be16(data, reg_thresh_rd); 398 if (ret < 0) 399 return ret; 400 401 + thresh = ret; 402 + ret = hdc3020_read_be16(data, reg_clr_rd); 403 + if (ret < 0) 404 + return ret; 405 + 406 + clr = ret; 407 + /* Scale value to include decimal part into calculations */ 408 + s_val = (val < 0) ? (val * 1000000 - val2) : (val * 1000000 + val2); 409 switch (chan->type) { 410 case IIO_TEMP: 411 + switch (info) { 412 + case IIO_EV_INFO_VALUE: 413 + s_val = max(s_val, HDC3020_MIN_TEMP_MICRO); 414 + s_val = min(s_val, HDC3020_MAX_TEMP_MICRO); 415 + reg = reg_thresh_wr; 416 + reg_val = hdc3020_thresh_set_temp(s_val, thresh); 417 + ret = _hdc3020_write_thresh(data, reg, reg_val); 418 + if (ret < 0) 419 + return ret; 420 + 421 + /* Calculate old hysteresis */ 422 + s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000; 423 + s_clr = (s64)hdc3020_thresh_get_temp(clr) * 1000000; 424 + s_hyst = div_s64(abs(s_thresh - s_clr), 65535); 425 + /* Set new threshold */ 426 + thresh = reg_val; 427 + /* Set old hysteresis */ 428 + s_val = s_hyst; 429 + fallthrough; 430 + case IIO_EV_INFO_HYSTERESIS: 431 + /* 432 + * Function hdc3020_thresh_get_temp returns temperature 433 + * in degree celsius scaled by 65535. Scale by 1000000 434 + * to be able to subtract scaled hysteresis value. 435 + */ 436 + s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000; 437 + /* 438 + * Units of s_val are in micro degree celsius, scale by 439 + * 65535 to get same units as s_thresh. 440 + */ 441 + s_val = min(abs(s_val), HDC3020_MAX_TEMP_HYST_MICRO); 442 + s_hyst = (s64)s_val * 65535; 443 + s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir); 444 + s_clr = max(s_clr, HDC3020_MIN_TEMP_MICRO); 445 + s_clr = min(s_clr, HDC3020_MAX_TEMP_MICRO); 446 + reg = reg_clr_wr; 447 + reg_val = hdc3020_thresh_set_temp(s_clr, clr); 448 + break; 449 + default: 450 + return -EOPNOTSUPP; 451 + } 452 break; 453 case IIO_HUMIDITYRELATIVE: 454 + s_val = (s_val < 0) ? 0 : min(s_val, HDC3020_MAX_HUM_MICRO); 455 + switch (info) { 456 + case IIO_EV_INFO_VALUE: 457 + reg = reg_thresh_wr; 458 + reg_val = hdc3020_thresh_set_hum(s_val, thresh); 459 + ret = _hdc3020_write_thresh(data, reg, reg_val); 460 + if (ret < 0) 461 + return ret; 462 + 463 + /* Calculate old hysteresis */ 464 + s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000; 465 + s_clr = (s64)hdc3020_thresh_get_hum(clr) * 1000000; 466 + s_hyst = div_s64(abs(s_thresh - s_clr), 65535); 467 + /* Set new threshold */ 468 + thresh = reg_val; 469 + /* Try to set old hysteresis */ 470 + s_val = min(abs(s_hyst), HDC3020_MAX_HUM_MICRO); 471 + fallthrough; 472 + case IIO_EV_INFO_HYSTERESIS: 473 + /* 474 + * Function hdc3020_thresh_get_hum returns relative 475 + * humidity in percent scaled by 65535. Scale by 1000000 476 + * to be able to subtract scaled hysteresis value. 477 + */ 478 + s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000; 479 + /* 480 + * Units of s_val are in micro percent, scale by 65535 481 + * to get same units as s_thresh. 482 + */ 483 + s_hyst = (s64)s_val * 65535; 484 + s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir); 485 + s_clr = max(s_clr, 0); 486 + s_clr = min(s_clr, HDC3020_MAX_HUM_MICRO); 487 + reg = reg_clr_wr; 488 + reg_val = hdc3020_thresh_set_hum(s_clr, clr); 489 + break; 490 + default: 491 + return -EOPNOTSUPP; 492 + } 493 break; 494 default: 495 return -EOPNOTSUPP; 496 } 497 498 + return _hdc3020_write_thresh(data, reg, reg_val); 499 } 500 501 static int hdc3020_read_thresh(struct iio_dev *indio_dev, ··· 447 int *val, int *val2) 448 { 449 struct hdc3020_data *data = iio_priv(indio_dev); 450 + u16 reg_thresh, reg_clr; 451 + int thresh, clr, ret; 452 453 + /* Select threshold registers */ 454 + if (dir == IIO_EV_DIR_RISING) { 455 + reg_thresh = HDC3020_R_T_RH_THRESH_HIGH; 456 + reg_clr = HDC3020_R_T_RH_THRESH_HIGH_CLR; 457 } else { 458 + reg_thresh = HDC3020_R_T_RH_THRESH_LOW; 459 + reg_clr = HDC3020_R_T_RH_THRESH_LOW_CLR; 460 } 461 462 guard(mutex)(&data->lock); 463 + ret = hdc3020_read_be16(data, reg_thresh); 464 if (ret < 0) 465 return ret; 466 467 switch (chan->type) { 468 case IIO_TEMP: 469 + thresh = hdc3020_thresh_get_temp(ret); 470 + switch (info) { 471 + case IIO_EV_INFO_VALUE: 472 + *val = thresh; 473 + break; 474 + case IIO_EV_INFO_HYSTERESIS: 475 + ret = hdc3020_read_be16(data, reg_clr); 476 + if (ret < 0) 477 + return ret; 478 + 479 + clr = hdc3020_thresh_get_temp(ret); 480 + *val = abs(thresh - clr); 481 + break; 482 + default: 483 + return -EOPNOTSUPP; 484 + } 485 *val2 = 65535; 486 return IIO_VAL_FRACTIONAL; 487 case IIO_HUMIDITYRELATIVE: 488 + thresh = hdc3020_thresh_get_hum(ret); 489 + switch (info) { 490 + case IIO_EV_INFO_VALUE: 491 + *val = thresh; 492 + break; 493 + case IIO_EV_INFO_HYSTERESIS: 494 + ret = hdc3020_read_be16(data, reg_clr); 495 + if (ret < 0) 496 + return ret; 497 + 498 + clr = hdc3020_thresh_get_hum(ret); 499 + *val = abs(thresh - clr); 500 + break; 501 + default: 502 + return -EOPNOTSUPP; 503 + } 504 *val2 = 65535; 505 return IIO_VAL_FRACTIONAL; 506 default: