diff options
Diffstat (limited to 'drivers/iio/humidity/hts221_core.c')
-rw-r--r-- | drivers/iio/humidity/hts221_core.c | 144 |
1 files changed, 51 insertions, 93 deletions
diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c index a56da3999e00..32524a8dc66f 100644 --- a/drivers/iio/humidity/hts221_core.c +++ b/drivers/iio/humidity/hts221_core.c @@ -23,7 +23,6 @@ #define HTS221_REG_CNTRL1_ADDR 0x20 #define HTS221_REG_CNTRL2_ADDR 0x21 -#define HTS221_REG_CNTRL3_ADDR 0x22 #define HTS221_REG_AVG_ADDR 0x10 #define HTS221_REG_H_OUT_L 0x28 @@ -32,30 +31,9 @@ #define HTS221_HUMIDITY_AVG_MASK 0x07 #define HTS221_TEMP_AVG_MASK 0x38 -#define HTS221_ODR_MASK 0x87 +#define HTS221_ODR_MASK 0x03 #define HTS221_BDU_MASK BIT(2) - -#define HTS221_DRDY_MASK BIT(2) - -#define HTS221_ENABLE_SENSOR BIT(7) - -#define HTS221_HUMIDITY_AVG_4 0x00 /* 0.4 %RH */ -#define HTS221_HUMIDITY_AVG_8 0x01 /* 0.3 %RH */ -#define HTS221_HUMIDITY_AVG_16 0x02 /* 0.2 %RH */ -#define HTS221_HUMIDITY_AVG_32 0x03 /* 0.15 %RH */ -#define HTS221_HUMIDITY_AVG_64 0x04 /* 0.1 %RH */ -#define HTS221_HUMIDITY_AVG_128 0x05 /* 0.07 %RH */ -#define HTS221_HUMIDITY_AVG_256 0x06 /* 0.05 %RH */ -#define HTS221_HUMIDITY_AVG_512 0x07 /* 0.03 %RH */ - -#define HTS221_TEMP_AVG_2 0x00 /* 0.08 degC */ -#define HTS221_TEMP_AVG_4 0x08 /* 0.05 degC */ -#define HTS221_TEMP_AVG_8 0x10 /* 0.04 degC */ -#define HTS221_TEMP_AVG_16 0x18 /* 0.03 degC */ -#define HTS221_TEMP_AVG_32 0x20 /* 0.02 degC */ -#define HTS221_TEMP_AVG_64 0x28 /* 0.015 degC */ -#define HTS221_TEMP_AVG_128 0x30 /* 0.01 degC */ -#define HTS221_TEMP_AVG_256 0x38 /* 0.007 degC */ +#define HTS221_ENABLE_MASK BIT(7) /* calibration registers */ #define HTS221_REG_0RH_CAL_X_H 0x36 @@ -73,10 +51,11 @@ struct hts221_odr { u8 val; }; +#define HTS221_AVG_DEPTH 8 struct hts221_avg { u8 addr; u8 mask; - struct hts221_avg_avl avg_avl[HTS221_AVG_DEPTH]; + u16 avg_avl[HTS221_AVG_DEPTH]; }; static const struct hts221_odr hts221_odr_table[] = { @@ -90,28 +69,28 @@ static const struct hts221_avg hts221_avg_list[] = { .addr = HTS221_REG_AVG_ADDR, .mask = HTS221_HUMIDITY_AVG_MASK, .avg_avl = { - { 4, HTS221_HUMIDITY_AVG_4 }, - { 8, HTS221_HUMIDITY_AVG_8 }, - { 16, HTS221_HUMIDITY_AVG_16 }, - { 32, HTS221_HUMIDITY_AVG_32 }, - { 64, HTS221_HUMIDITY_AVG_64 }, - { 128, HTS221_HUMIDITY_AVG_128 }, - { 256, HTS221_HUMIDITY_AVG_256 }, - { 512, HTS221_HUMIDITY_AVG_512 }, + 4, /* 0.4 %RH */ + 8, /* 0.3 %RH */ + 16, /* 0.2 %RH */ + 32, /* 0.15 %RH */ + 64, /* 0.1 %RH */ + 128, /* 0.07 %RH */ + 256, /* 0.05 %RH */ + 512, /* 0.03 %RH */ }, }, { .addr = HTS221_REG_AVG_ADDR, .mask = HTS221_TEMP_AVG_MASK, .avg_avl = { - { 2, HTS221_TEMP_AVG_2 }, - { 4, HTS221_TEMP_AVG_4 }, - { 8, HTS221_TEMP_AVG_8 }, - { 16, HTS221_TEMP_AVG_16 }, - { 32, HTS221_TEMP_AVG_32 }, - { 64, HTS221_TEMP_AVG_64 }, - { 128, HTS221_TEMP_AVG_128 }, - { 256, HTS221_TEMP_AVG_256 }, + 2, /* 0.08 degC */ + 4, /* 0.05 degC */ + 8, /* 0.04 degC */ + 16, /* 0.03 degC */ + 32, /* 0.02 degC */ + 64, /* 0.015 degC */ + 128, /* 0.01 degC */ + 256, /* 0.007 degC */ }, }, }; @@ -152,8 +131,7 @@ static const struct iio_chan_spec hts221_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(2), }; -static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, - u8 val) +int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, u8 val) { u8 data; int err; @@ -166,7 +144,7 @@ static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, goto unlock; } - data = (data & ~mask) | (val & mask); + data = (data & ~mask) | ((val << __ffs(mask)) & mask); err = hw->tf->write(hw->dev, addr, sizeof(data), &data); if (err < 0) @@ -199,21 +177,9 @@ static int hts221_check_whoami(struct hts221_hw *hw) return 0; } -int hts221_config_drdy(struct hts221_hw *hw, bool enable) -{ - u8 val = enable ? BIT(2) : 0; - int err; - - err = hts221_write_with_mask(hw, HTS221_REG_CNTRL3_ADDR, - HTS221_DRDY_MASK, val); - - return err < 0 ? err : 0; -} - static int hts221_update_odr(struct hts221_hw *hw, u8 odr) { int i, err; - u8 val; for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++) if (hts221_odr_table[i].hz == odr) @@ -222,9 +188,8 @@ static int hts221_update_odr(struct hts221_hw *hw, u8 odr) if (i == ARRAY_SIZE(hts221_odr_table)) return -EINVAL; - val = HTS221_ENABLE_SENSOR | HTS221_BDU_MASK | hts221_odr_table[i].val; err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, - HTS221_ODR_MASK, val); + HTS221_ODR_MASK, hts221_odr_table[i].val); if (err < 0) return err; @@ -241,14 +206,13 @@ static int hts221_update_avg(struct hts221_hw *hw, const struct hts221_avg *avg = &hts221_avg_list[type]; for (i = 0; i < HTS221_AVG_DEPTH; i++) - if (avg->avg_avl[i].avg == val) + if (avg->avg_avl[i] == val) break; if (i == HTS221_AVG_DEPTH) return -EINVAL; - err = hts221_write_with_mask(hw, avg->addr, avg->mask, - avg->avg_avl[i].val); + err = hts221_write_with_mask(hw, avg->addr, avg->mask, i); if (err < 0) return err; @@ -283,7 +247,7 @@ hts221_sysfs_rh_oversampling_avail(struct device *dev, for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", - avg->avg_avl[i].avg); + avg->avg_avl[i]); buf[len - 1] = '\n'; return len; @@ -300,36 +264,22 @@ hts221_sysfs_temp_oversampling_avail(struct device *dev, for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", - avg->avg_avl[i].avg); + avg->avg_avl[i]); buf[len - 1] = '\n'; return len; } -int hts221_power_on(struct hts221_hw *hw) -{ - int err; - - err = hts221_update_odr(hw, hw->odr); - if (err < 0) - return err; - - hw->enabled = true; - - return 0; -} - -int hts221_power_off(struct hts221_hw *hw) +int hts221_set_enable(struct hts221_hw *hw, bool enable) { - __le16 data = 0; int err; - err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), - (u8 *)&data); + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, + HTS221_ENABLE_MASK, enable); if (err < 0) return err; - hw->enabled = false; + hw->enabled = enable; return 0; } @@ -484,7 +434,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) u8 data[HTS221_DATA_SIZE]; int err; - err = hts221_power_on(hw); + err = hts221_set_enable(hw, true); if (err < 0) return err; @@ -494,7 +444,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) if (err < 0) return err; - hts221_power_off(hw); + hts221_set_enable(hw, false); *val = (s16)get_unaligned_le16(data); @@ -534,13 +484,13 @@ static int hts221_read_raw(struct iio_dev *iio_dev, case IIO_HUMIDITYRELATIVE: avg = &hts221_avg_list[HTS221_SENSOR_H]; idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx; - *val = avg->avg_avl[idx].avg; + *val = avg->avg_avl[idx]; ret = IIO_VAL_INT; break; case IIO_TEMP: avg = &hts221_avg_list[HTS221_SENSOR_T]; idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx; - *val = avg->avg_avl[idx].avg; + *val = avg->avg_avl[idx]; ret = IIO_VAL_INT; break; default: @@ -644,8 +594,6 @@ int hts221_probe(struct iio_dev *iio_dev) if (err < 0) return err; - hw->odr = hts221_odr_table[0].hz; - iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->dev.parent = hw->dev; iio_dev->available_scan_masks = hts221_scan_masks; @@ -654,6 +602,16 @@ int hts221_probe(struct iio_dev *iio_dev) iio_dev->name = HTS221_DEV_NAME; iio_dev->info = &hts221_info; + /* enable Block Data Update */ + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, + HTS221_BDU_MASK, 1); + if (err < 0) + return err; + + err = hts221_update_odr(hw, hts221_odr_table[0].hz); + if (err < 0) + return err; + /* configure humidity sensor */ err = hts221_parse_rh_caldata(hw); if (err < 0) { @@ -661,7 +619,7 @@ int hts221_probe(struct iio_dev *iio_dev) return err; } - data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3].avg; + data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3]; err = hts221_update_avg(hw, HTS221_SENSOR_H, data); if (err < 0) { dev_err(hw->dev, "failed to set rh oversampling ratio\n"); @@ -676,7 +634,7 @@ int hts221_probe(struct iio_dev *iio_dev) return err; } - data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3].avg; + data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3]; err = hts221_update_avg(hw, HTS221_SENSOR_T, data); if (err < 0) { dev_err(hw->dev, @@ -702,11 +660,10 @@ static int __maybe_unused hts221_suspend(struct device *dev) { struct iio_dev *iio_dev = dev_get_drvdata(dev); struct hts221_hw *hw = iio_priv(iio_dev); - __le16 data = 0; int err; - err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), - (u8 *)&data); + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, + HTS221_ENABLE_MASK, false); return err < 0 ? err : 0; } @@ -718,7 +675,8 @@ static int __maybe_unused hts221_resume(struct device *dev) int err = 0; if (hw->enabled) - err = hts221_update_odr(hw, hw->odr); + err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, + HTS221_ENABLE_MASK, true); return err; } |