Char/Misc driver fixes for 6.10-rc6
Here are some small driver fixes for 6.10-rc6. Included in here are: - IIO driver fixes for reported issues - Counter driver fix for a reported problem. All of these have been in linux-next this week with no reported issues Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZoFlrA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymiMQCgkUmsCT9KQDt+/IqClfL+A6nBvUkAn08jRwGA dXjTvroHgHsNCU/VXMwV =FcWr -----END PGP SIGNATURE----- Merge tag 'char-misc-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc driver fixes from Greg KH: "Here are some small driver fixes for 6.10-rc6. Included in here are: - IIO driver fixes for reported issues - Counter driver fix for a reported problem. All of these have been in linux-next this week with no reported issues" * tag 'char-misc-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: counter: ti-eqep: enable clock at probe 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
This commit is contained in:
commit
84dd4373d5
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/counter.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
@ -376,6 +377,7 @@ static int ti_eqep_probe(struct platform_device *pdev)
|
||||
struct counter_device *counter;
|
||||
struct ti_eqep_cnt *priv;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
int err;
|
||||
|
||||
counter = devm_counter_alloc(dev, sizeof(*priv));
|
||||
@ -415,6 +417,10 @@ static int ti_eqep_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return dev_err_probe(dev, PTR_ERR(clk), "failed to enable clock\n");
|
||||
|
||||
err = counter_add(counter);
|
||||
if (err < 0) {
|
||||
pm_runtime_put_sync(dev);
|
||||
|
@ -330,6 +330,8 @@ config DMARD10
|
||||
config FXLS8962AF
|
||||
tristate
|
||||
depends on I2C || !I2C # cannot be built-in for modular I2C
|
||||
select IIO_BUFFER
|
||||
select IIO_KFIFO_BUF
|
||||
|
||||
config FXLS8962AF_I2C
|
||||
tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver"
|
||||
|
@ -157,6 +157,8 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
|
||||
ret = ad7266_read_single(st, val, chan->address);
|
||||
iio_device_release_direct_mode(indio_dev);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = (*val >> 2) & 0xfff;
|
||||
if (chan->scan_type.sign == 's')
|
||||
*val = sign_extend32(*val,
|
||||
|
@ -414,8 +414,12 @@ static void ams_enable_channel_sequence(struct iio_dev *indio_dev)
|
||||
|
||||
/* Run calibration of PS & PL as part of the sequence */
|
||||
scan_mask = BIT(0) | BIT(AMS_PS_SEQ_MAX);
|
||||
for (i = 0; i < indio_dev->num_channels; i++)
|
||||
scan_mask |= BIT_ULL(indio_dev->channels[i].scan_index);
|
||||
for (i = 0; i < indio_dev->num_channels; i++) {
|
||||
const struct iio_chan_spec *chan = &indio_dev->channels[i];
|
||||
|
||||
if (chan->scan_index < AMS_CTRL_SEQ_BASE)
|
||||
scan_mask |= BIT_ULL(chan->scan_index);
|
||||
}
|
||||
|
||||
if (ams->ps_base) {
|
||||
/* put sysmon in a soft reset to change the sequence */
|
||||
|
@ -54,7 +54,9 @@
|
||||
#define BME680_NB_CONV_MASK GENMASK(3, 0)
|
||||
|
||||
#define BME680_REG_MEAS_STAT_0 0x1D
|
||||
#define BME680_NEW_DATA_BIT BIT(7)
|
||||
#define BME680_GAS_MEAS_BIT BIT(6)
|
||||
#define BME680_MEAS_BIT BIT(5)
|
||||
|
||||
/* Calibration Parameters */
|
||||
#define BME680_T2_LSB_REG 0x8A
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/log2.h>
|
||||
@ -38,7 +39,7 @@ struct bme680_calib {
|
||||
s8 par_h3;
|
||||
s8 par_h4;
|
||||
s8 par_h5;
|
||||
s8 par_h6;
|
||||
u8 par_h6;
|
||||
s8 par_h7;
|
||||
s8 par_gh1;
|
||||
s16 par_gh2;
|
||||
@ -342,10 +343,10 @@ static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
if (!calib->par_t2)
|
||||
bme680_read_calib(data, calib);
|
||||
|
||||
var1 = (adc_temp >> 3) - (calib->par_t1 << 1);
|
||||
var1 = (adc_temp >> 3) - ((s32)calib->par_t1 << 1);
|
||||
var2 = (var1 * calib->par_t2) >> 11;
|
||||
var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
|
||||
var3 = (var3 * (calib->par_t3 << 4)) >> 14;
|
||||
var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14;
|
||||
data->t_fine = var2 + var3;
|
||||
calc_temp = (data->t_fine * 5 + 128) >> 8;
|
||||
|
||||
@ -368,9 +369,9 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
var1 = (data->t_fine >> 1) - 64000;
|
||||
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2;
|
||||
var2 = var2 + (var1 * calib->par_p5 << 1);
|
||||
var2 = (var2 >> 2) + (calib->par_p4 << 16);
|
||||
var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16);
|
||||
var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
|
||||
(calib->par_p3 << 5)) >> 3) +
|
||||
((s32)calib->par_p3 << 5)) >> 3) +
|
||||
((calib->par_p2 * var1) >> 1);
|
||||
var1 = var1 >> 18;
|
||||
var1 = ((32768 + var1) * calib->par_p1) >> 15;
|
||||
@ -388,7 +389,7 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
var3 = ((press_comp >> 8) * (press_comp >> 8) *
|
||||
(press_comp >> 8) * calib->par_p10) >> 17;
|
||||
|
||||
press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4;
|
||||
press_comp += (var1 + var2 + var3 + ((s32)calib->par_p7 << 7)) >> 4;
|
||||
|
||||
return press_comp;
|
||||
}
|
||||
@ -414,7 +415,7 @@ static u32 bme680_compensate_humid(struct bme680_data *data,
|
||||
(((temp_scaled * ((temp_scaled * calib->par_h5) / 100))
|
||||
>> 6) / 100) + (1 << 14))) >> 10;
|
||||
var3 = var1 * var2;
|
||||
var4 = calib->par_h6 << 7;
|
||||
var4 = (s32)calib->par_h6 << 7;
|
||||
var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4;
|
||||
var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
|
||||
var6 = (var4 * var5) >> 1;
|
||||
@ -532,6 +533,43 @@ static u8 bme680_oversampling_to_reg(u8 val)
|
||||
return ilog2(val) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken from Bosch BME680 API:
|
||||
* https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L490
|
||||
*/
|
||||
static int bme680_wait_for_eoc(struct bme680_data *data)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
unsigned int check;
|
||||
int ret;
|
||||
/*
|
||||
* (Sum of oversampling ratios * time per oversampling) +
|
||||
* TPH measurement + gas measurement + wait transition from forced mode
|
||||
* + heater duration
|
||||
*/
|
||||
int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press +
|
||||
data->oversampling_humid) * 1936) + (477 * 4) +
|
||||
(477 * 5) + 1000 + (data->heater_dur * 1000);
|
||||
|
||||
usleep_range(wait_eoc_us, wait_eoc_us + 100);
|
||||
|
||||
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to read measurement status register.\n");
|
||||
return ret;
|
||||
}
|
||||
if (check & BME680_MEAS_BIT) {
|
||||
dev_err(dev, "Device measurement cycle incomplete.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (!(check & BME680_NEW_DATA_BIT)) {
|
||||
dev_err(dev, "No new data available from the device.\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bme680_chip_config(struct bme680_data *data)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
@ -622,6 +660,10 @@ static int bme680_read_temp(struct bme680_data *data, int *val)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = bme680_wait_for_eoc(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
|
||||
&tmp, 3);
|
||||
if (ret < 0) {
|
||||
@ -678,7 +720,7 @@ static int bme680_read_press(struct bme680_data *data,
|
||||
}
|
||||
|
||||
*val = bme680_compensate_press(data, adc_press);
|
||||
*val2 = 100;
|
||||
*val2 = 1000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
}
|
||||
|
||||
@ -738,6 +780,10 @@ static int bme680_read_gas(struct bme680_data *data,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = bme680_wait_for_eoc(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
|
||||
if (check & BME680_GAS_MEAS_BIT) {
|
||||
dev_err(dev, "gas measurement incomplete\n");
|
||||
|
@ -133,7 +133,7 @@ config AD5624R_SPI
|
||||
|
||||
config AD9739A
|
||||
tristate "Analog Devices AD9739A RF DAC spi driver"
|
||||
depends on SPI || COMPILE_TEST
|
||||
depends on SPI
|
||||
select REGMAP_SPI
|
||||
select IIO_BACKEND
|
||||
help
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm.h>
|
||||
@ -66,8 +67,10 @@
|
||||
|
||||
#define HDC3020_CRC8_POLYNOMIAL 0x31
|
||||
|
||||
#define HDC3020_MIN_TEMP -40
|
||||
#define HDC3020_MAX_TEMP 125
|
||||
#define HDC3020_MIN_TEMP_MICRO -39872968
|
||||
#define HDC3020_MAX_TEMP_MICRO 124875639
|
||||
#define HDC3020_MAX_TEMP_HYST_MICRO 164748607
|
||||
#define HDC3020_MAX_HUM_MICRO 99220264
|
||||
|
||||
struct hdc3020_data {
|
||||
struct i2c_client *client;
|
||||
@ -368,6 +371,105 @@ static int hdc3020_write_raw(struct iio_dev *indio_dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int hdc3020_thresh_get_temp(u16 thresh)
|
||||
{
|
||||
int temp;
|
||||
|
||||
/*
|
||||
* Get the temperature threshold from 9 LSBs, shift them to get
|
||||
* the truncated temperature threshold representation and
|
||||
* calculate the threshold according to the formula in the
|
||||
* datasheet. Result is degree celsius scaled by 65535.
|
||||
*/
|
||||
temp = FIELD_GET(HDC3020_THRESH_TEMP_MASK, thresh) <<
|
||||
HDC3020_THRESH_TEMP_TRUNC_SHIFT;
|
||||
|
||||
return -2949075 + (175 * temp);
|
||||
}
|
||||
|
||||
static int hdc3020_thresh_get_hum(u16 thresh)
|
||||
{
|
||||
int hum;
|
||||
|
||||
/*
|
||||
* Get the humidity threshold from 7 MSBs, shift them to get the
|
||||
* truncated humidity threshold representation and calculate the
|
||||
* threshold according to the formula in the datasheet. Result is
|
||||
* percent scaled by 65535.
|
||||
*/
|
||||
hum = FIELD_GET(HDC3020_THRESH_HUM_MASK, thresh) <<
|
||||
HDC3020_THRESH_HUM_TRUNC_SHIFT;
|
||||
|
||||
return hum * 100;
|
||||
}
|
||||
|
||||
static u16 hdc3020_thresh_set_temp(int s_temp, u16 curr_thresh)
|
||||
{
|
||||
u64 temp;
|
||||
u16 thresh;
|
||||
|
||||
/*
|
||||
* Calculate temperature threshold, shift it down to get the
|
||||
* truncated threshold representation in the 9LSBs while keeping
|
||||
* the current humidity threshold in the 7 MSBs.
|
||||
*/
|
||||
temp = (u64)(s_temp + 45000000) * 65535ULL;
|
||||
temp = div_u64(temp, 1000000 * 175) >> HDC3020_THRESH_TEMP_TRUNC_SHIFT;
|
||||
thresh = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, temp);
|
||||
thresh |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, curr_thresh) <<
|
||||
HDC3020_THRESH_HUM_TRUNC_SHIFT);
|
||||
|
||||
return thresh;
|
||||
}
|
||||
|
||||
static u16 hdc3020_thresh_set_hum(int s_hum, u16 curr_thresh)
|
||||
{
|
||||
u64 hum;
|
||||
u16 thresh;
|
||||
|
||||
/*
|
||||
* Calculate humidity threshold, shift it down and up to get the
|
||||
* truncated threshold representation in the 7MSBs while keeping
|
||||
* the current temperature threshold in the 9 LSBs.
|
||||
*/
|
||||
hum = (u64)(s_hum) * 65535ULL;
|
||||
hum = div_u64(hum, 1000000 * 100) >> HDC3020_THRESH_HUM_TRUNC_SHIFT;
|
||||
thresh = FIELD_PREP(HDC3020_THRESH_HUM_MASK, hum);
|
||||
thresh |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, curr_thresh);
|
||||
|
||||
return thresh;
|
||||
}
|
||||
|
||||
static
|
||||
int hdc3020_thresh_clr(s64 s_thresh, s64 s_hyst, enum iio_event_direction dir)
|
||||
{
|
||||
s64 s_clr;
|
||||
|
||||
/*
|
||||
* Include directions when calculation the clear value,
|
||||
* since hysteresis is unsigned by definition and the
|
||||
* clear value is an absolute value which is signed.
|
||||
*/
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
s_clr = s_thresh - s_hyst;
|
||||
else
|
||||
s_clr = s_thresh + s_hyst;
|
||||
|
||||
/* Divide by 65535 to get units of micro */
|
||||
return div_s64(s_clr, 65535);
|
||||
}
|
||||
|
||||
static int _hdc3020_write_thresh(struct hdc3020_data *data, u16 reg, u16 val)
|
||||
{
|
||||
u8 buf[5];
|
||||
|
||||
put_unaligned_be16(reg, buf);
|
||||
put_unaligned_be16(val, buf + 2);
|
||||
buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
|
||||
|
||||
return hdc3020_write_bytes(data, buf, 5);
|
||||
}
|
||||
|
||||
static int hdc3020_write_thresh(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
@ -376,67 +478,126 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
|
||||
int val, int val2)
|
||||
{
|
||||
struct hdc3020_data *data = iio_priv(indio_dev);
|
||||
u8 buf[5];
|
||||
u64 tmp;
|
||||
u16 reg;
|
||||
int ret;
|
||||
u16 reg, reg_val, reg_thresh_rd, reg_clr_rd, reg_thresh_wr, reg_clr_wr;
|
||||
s64 s_thresh, s_hyst, s_clr;
|
||||
int s_val, thresh, clr, ret;
|
||||
|
||||
/* Supported temperature range is from –40 to 125 degree celsius */
|
||||
if (val < HDC3020_MIN_TEMP || val > HDC3020_MAX_TEMP)
|
||||
return -EINVAL;
|
||||
|
||||
/* Select threshold register */
|
||||
if (info == IIO_EV_INFO_VALUE) {
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = HDC3020_S_T_RH_THRESH_HIGH;
|
||||
else
|
||||
reg = HDC3020_S_T_RH_THRESH_LOW;
|
||||
/* Select threshold registers */
|
||||
if (dir == IIO_EV_DIR_RISING) {
|
||||
reg_thresh_rd = HDC3020_R_T_RH_THRESH_HIGH;
|
||||
reg_thresh_wr = HDC3020_S_T_RH_THRESH_HIGH;
|
||||
reg_clr_rd = HDC3020_R_T_RH_THRESH_HIGH_CLR;
|
||||
reg_clr_wr = HDC3020_S_T_RH_THRESH_HIGH_CLR;
|
||||
} else {
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = HDC3020_S_T_RH_THRESH_HIGH_CLR;
|
||||
else
|
||||
reg = HDC3020_S_T_RH_THRESH_LOW_CLR;
|
||||
reg_thresh_rd = HDC3020_R_T_RH_THRESH_LOW;
|
||||
reg_thresh_wr = HDC3020_S_T_RH_THRESH_LOW;
|
||||
reg_clr_rd = HDC3020_R_T_RH_THRESH_LOW_CLR;
|
||||
reg_clr_wr = HDC3020_S_T_RH_THRESH_LOW_CLR;
|
||||
}
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
ret = hdc3020_read_be16(data, reg);
|
||||
ret = hdc3020_read_be16(data, reg_thresh_rd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
thresh = ret;
|
||||
ret = hdc3020_read_be16(data, reg_clr_rd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clr = ret;
|
||||
/* Scale value to include decimal part into calculations */
|
||||
s_val = (val < 0) ? (val * 1000000 - val2) : (val * 1000000 + val2);
|
||||
switch (chan->type) {
|
||||
case IIO_TEMP:
|
||||
/*
|
||||
* Calculate temperature threshold, shift it down to get the
|
||||
* truncated threshold representation in the 9LSBs while keeping
|
||||
* the current humidity threshold in the 7 MSBs.
|
||||
*/
|
||||
tmp = ((u64)(((val + 45) * MICRO) + val2)) * 65535ULL;
|
||||
tmp = div_u64(tmp, MICRO * 175);
|
||||
val = tmp >> HDC3020_THRESH_TEMP_TRUNC_SHIFT;
|
||||
val = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, val);
|
||||
val |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, ret) <<
|
||||
HDC3020_THRESH_HUM_TRUNC_SHIFT);
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
s_val = max(s_val, HDC3020_MIN_TEMP_MICRO);
|
||||
s_val = min(s_val, HDC3020_MAX_TEMP_MICRO);
|
||||
reg = reg_thresh_wr;
|
||||
reg_val = hdc3020_thresh_set_temp(s_val, thresh);
|
||||
ret = _hdc3020_write_thresh(data, reg, reg_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Calculate old hysteresis */
|
||||
s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000;
|
||||
s_clr = (s64)hdc3020_thresh_get_temp(clr) * 1000000;
|
||||
s_hyst = div_s64(abs(s_thresh - s_clr), 65535);
|
||||
/* Set new threshold */
|
||||
thresh = reg_val;
|
||||
/* Set old hysteresis */
|
||||
s_val = s_hyst;
|
||||
fallthrough;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
/*
|
||||
* Function hdc3020_thresh_get_temp returns temperature
|
||||
* in degree celsius scaled by 65535. Scale by 1000000
|
||||
* to be able to subtract scaled hysteresis value.
|
||||
*/
|
||||
s_thresh = (s64)hdc3020_thresh_get_temp(thresh) * 1000000;
|
||||
/*
|
||||
* Units of s_val are in micro degree celsius, scale by
|
||||
* 65535 to get same units as s_thresh.
|
||||
*/
|
||||
s_val = min(abs(s_val), HDC3020_MAX_TEMP_HYST_MICRO);
|
||||
s_hyst = (s64)s_val * 65535;
|
||||
s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir);
|
||||
s_clr = max(s_clr, HDC3020_MIN_TEMP_MICRO);
|
||||
s_clr = min(s_clr, HDC3020_MAX_TEMP_MICRO);
|
||||
reg = reg_clr_wr;
|
||||
reg_val = hdc3020_thresh_set_temp(s_clr, clr);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case IIO_HUMIDITYRELATIVE:
|
||||
/*
|
||||
* Calculate humidity threshold, shift it down and up to get the
|
||||
* truncated threshold representation in the 7MSBs while keeping
|
||||
* the current temperature threshold in the 9 LSBs.
|
||||
*/
|
||||
tmp = ((u64)((val * MICRO) + val2)) * 65535ULL;
|
||||
tmp = div_u64(tmp, MICRO * 100);
|
||||
val = tmp >> HDC3020_THRESH_HUM_TRUNC_SHIFT;
|
||||
val = FIELD_PREP(HDC3020_THRESH_HUM_MASK, val);
|
||||
val |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
|
||||
s_val = (s_val < 0) ? 0 : min(s_val, HDC3020_MAX_HUM_MICRO);
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
reg = reg_thresh_wr;
|
||||
reg_val = hdc3020_thresh_set_hum(s_val, thresh);
|
||||
ret = _hdc3020_write_thresh(data, reg, reg_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Calculate old hysteresis */
|
||||
s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000;
|
||||
s_clr = (s64)hdc3020_thresh_get_hum(clr) * 1000000;
|
||||
s_hyst = div_s64(abs(s_thresh - s_clr), 65535);
|
||||
/* Set new threshold */
|
||||
thresh = reg_val;
|
||||
/* Try to set old hysteresis */
|
||||
s_val = min(abs(s_hyst), HDC3020_MAX_HUM_MICRO);
|
||||
fallthrough;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
/*
|
||||
* Function hdc3020_thresh_get_hum returns relative
|
||||
* humidity in percent scaled by 65535. Scale by 1000000
|
||||
* to be able to subtract scaled hysteresis value.
|
||||
*/
|
||||
s_thresh = (s64)hdc3020_thresh_get_hum(thresh) * 1000000;
|
||||
/*
|
||||
* Units of s_val are in micro percent, scale by 65535
|
||||
* to get same units as s_thresh.
|
||||
*/
|
||||
s_hyst = (s64)s_val * 65535;
|
||||
s_clr = hdc3020_thresh_clr(s_thresh, s_hyst, dir);
|
||||
s_clr = max(s_clr, 0);
|
||||
s_clr = min(s_clr, HDC3020_MAX_HUM_MICRO);
|
||||
reg = reg_clr_wr;
|
||||
reg_val = hdc3020_thresh_set_hum(s_clr, clr);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
put_unaligned_be16(reg, buf);
|
||||
put_unaligned_be16(val, buf + 2);
|
||||
buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
|
||||
return hdc3020_write_bytes(data, buf, 5);
|
||||
return _hdc3020_write_thresh(data, reg, reg_val);
|
||||
}
|
||||
|
||||
static int hdc3020_read_thresh(struct iio_dev *indio_dev,
|
||||
@ -447,48 +608,60 @@ static int hdc3020_read_thresh(struct iio_dev *indio_dev,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct hdc3020_data *data = iio_priv(indio_dev);
|
||||
u16 reg;
|
||||
int ret;
|
||||
u16 reg_thresh, reg_clr;
|
||||
int thresh, clr, ret;
|
||||
|
||||
/* Select threshold register */
|
||||
if (info == IIO_EV_INFO_VALUE) {
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = HDC3020_R_T_RH_THRESH_HIGH;
|
||||
else
|
||||
reg = HDC3020_R_T_RH_THRESH_LOW;
|
||||
/* Select threshold registers */
|
||||
if (dir == IIO_EV_DIR_RISING) {
|
||||
reg_thresh = HDC3020_R_T_RH_THRESH_HIGH;
|
||||
reg_clr = HDC3020_R_T_RH_THRESH_HIGH_CLR;
|
||||
} else {
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = HDC3020_R_T_RH_THRESH_HIGH_CLR;
|
||||
else
|
||||
reg = HDC3020_R_T_RH_THRESH_LOW_CLR;
|
||||
reg_thresh = HDC3020_R_T_RH_THRESH_LOW;
|
||||
reg_clr = HDC3020_R_T_RH_THRESH_LOW_CLR;
|
||||
}
|
||||
|
||||
guard(mutex)(&data->lock);
|
||||
ret = hdc3020_read_be16(data, reg);
|
||||
ret = hdc3020_read_be16(data, reg_thresh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_TEMP:
|
||||
/*
|
||||
* Get the temperature threshold from 9 LSBs, shift them to get
|
||||
* the truncated temperature threshold representation and
|
||||
* calculate the threshold according to the formula in the
|
||||
* datasheet.
|
||||
*/
|
||||
*val = FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
|
||||
*val = *val << HDC3020_THRESH_TEMP_TRUNC_SHIFT;
|
||||
*val = -2949075 + (175 * (*val));
|
||||
thresh = hdc3020_thresh_get_temp(ret);
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
*val = thresh;
|
||||
break;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
ret = hdc3020_read_be16(data, reg_clr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clr = hdc3020_thresh_get_temp(ret);
|
||||
*val = abs(thresh - clr);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
*val2 = 65535;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
case IIO_HUMIDITYRELATIVE:
|
||||
/*
|
||||
* Get the humidity threshold from 7 MSBs, shift them to get the
|
||||
* truncated humidity threshold representation and calculate the
|
||||
* threshold according to the formula in the datasheet.
|
||||
*/
|
||||
*val = FIELD_GET(HDC3020_THRESH_HUM_MASK, ret);
|
||||
*val = (*val << HDC3020_THRESH_HUM_TRUNC_SHIFT) * 100;
|
||||
thresh = hdc3020_thresh_get_hum(ret);
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
*val = thresh;
|
||||
break;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
ret = hdc3020_read_be16(data, reg_clr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clr = hdc3020_thresh_get_hum(ret);
|
||||
*val = abs(thresh - clr);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
*val2 = 65535;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user