1c524fbcaSJoshua Felmeden // SPDX-License-Identifier: GPL-2.0+ 2c524fbcaSJoshua Felmeden /* 3c524fbcaSJoshua Felmeden * ens210.c - Support for ScioSense ens210 temperature & humidity sensor family 4c524fbcaSJoshua Felmeden * 5c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x43 ENS210) 6c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x43 ENS210A) 7c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x44 ENS211) 8c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x45 ENS212) 9c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x46 ENS213A) 10c524fbcaSJoshua Felmeden * (7-bit I2C slave address 0x47 ENS215) 11c524fbcaSJoshua Felmeden * 12c524fbcaSJoshua Felmeden * Datasheet: 13c524fbcaSJoshua Felmeden * https://www.sciosense.com/wp-content/uploads/2024/04/ENS21x-Datasheet.pdf 14c524fbcaSJoshua Felmeden * https://www.sciosense.com/wp-content/uploads/2023/12/ENS210-Datasheet.pdf 15c524fbcaSJoshua Felmeden */ 16c524fbcaSJoshua Felmeden 17c524fbcaSJoshua Felmeden #include <linux/crc7.h> 18c524fbcaSJoshua Felmeden #include <linux/delay.h> 19c524fbcaSJoshua Felmeden #include <linux/i2c.h> 20c524fbcaSJoshua Felmeden #include <linux/iio/iio.h> 21c524fbcaSJoshua Felmeden #include <linux/mod_devicetable.h> 22c524fbcaSJoshua Felmeden #include <linux/module.h> 23c524fbcaSJoshua Felmeden #include <linux/types.h> 24c524fbcaSJoshua Felmeden 25*5f60d5f6SAl Viro #include <linux/unaligned.h> 26c524fbcaSJoshua Felmeden 27c524fbcaSJoshua Felmeden /* register definitions */ 28c524fbcaSJoshua Felmeden #define ENS210_REG_PART_ID 0x00 29c524fbcaSJoshua Felmeden #define ENS210_REG_DIE_REV 0x02 30c524fbcaSJoshua Felmeden #define ENS210_REG_UID 0x04 31c524fbcaSJoshua Felmeden #define ENS210_REG_SYS_CTRL 0x10 32c524fbcaSJoshua Felmeden #define ENS210_REG_SYS_STAT 0x11 33c524fbcaSJoshua Felmeden #define ENS210_REG_SENS_RUN 0x21 34c524fbcaSJoshua Felmeden #define ENS210_REG_SENS_START 0x22 35c524fbcaSJoshua Felmeden #define ENS210_REG_SENS_STOP 0x23 36c524fbcaSJoshua Felmeden #define ENS210_REG_SENS_STAT 0x24 37c524fbcaSJoshua Felmeden #define ENS210_REG_T_VAL 0x30 38c524fbcaSJoshua Felmeden #define ENS210_REG_H_VAL 0x33 39c524fbcaSJoshua Felmeden 40c524fbcaSJoshua Felmeden /* value definitions */ 41c524fbcaSJoshua Felmeden #define ENS210_SENS_START_T_START BIT(0) 42c524fbcaSJoshua Felmeden #define ENS210_SENS_START_H_START BIT(1) 43c524fbcaSJoshua Felmeden 44c524fbcaSJoshua Felmeden #define ENS210_SENS_STAT_T_ACTIVE BIT(0) 45c524fbcaSJoshua Felmeden #define ENS210_SENS_STAT_H_ACTIVE BIT(1) 46c524fbcaSJoshua Felmeden 47c524fbcaSJoshua Felmeden #define ENS210_SYS_CTRL_LOW_POWER_ENABLE BIT(0) 48c524fbcaSJoshua Felmeden #define ENS210_SYS_CTRL_SYS_RESET BIT(7) 49c524fbcaSJoshua Felmeden 50c524fbcaSJoshua Felmeden #define ENS210_SYS_STAT_SYS_ACTIVE BIT(0) 51c524fbcaSJoshua Felmeden 52c524fbcaSJoshua Felmeden enum ens210_partnumber { 53c524fbcaSJoshua Felmeden ENS210 = 0x0210, 54c524fbcaSJoshua Felmeden ENS210A = 0xa210, 55c524fbcaSJoshua Felmeden ENS211 = 0x0211, 56c524fbcaSJoshua Felmeden ENS212 = 0x0212, 57c524fbcaSJoshua Felmeden ENS213A = 0xa213, 58c524fbcaSJoshua Felmeden ENS215 = 0x0215, 59c524fbcaSJoshua Felmeden }; 60c524fbcaSJoshua Felmeden 61c524fbcaSJoshua Felmeden /** 62c524fbcaSJoshua Felmeden * struct ens210_chip_info - Humidity/Temperature chip specific information 63c524fbcaSJoshua Felmeden * @name: name of device 64c524fbcaSJoshua Felmeden * @part_id: chip identifier 65c524fbcaSJoshua Felmeden * @conv_time_msec: time for conversion calculation in m/s 66c524fbcaSJoshua Felmeden */ 67c524fbcaSJoshua Felmeden struct ens210_chip_info { 68c524fbcaSJoshua Felmeden const char *name; 69c524fbcaSJoshua Felmeden enum ens210_partnumber part_id; 70c524fbcaSJoshua Felmeden unsigned int conv_time_msec; 71c524fbcaSJoshua Felmeden }; 72c524fbcaSJoshua Felmeden 73c524fbcaSJoshua Felmeden /** 74c524fbcaSJoshua Felmeden * struct ens210_data - Humidity/Temperature sensor device structure 75c524fbcaSJoshua Felmeden * @client: i2c client 76c524fbcaSJoshua Felmeden * @chip_info: chip specific information 77c524fbcaSJoshua Felmeden * @lock: lock protecting against simultaneous callers of get_measurement 78c524fbcaSJoshua Felmeden * since multiple uninterrupted transactions are required 79c524fbcaSJoshua Felmeden */ 80c524fbcaSJoshua Felmeden struct ens210_data { 81c524fbcaSJoshua Felmeden struct i2c_client *client; 82c524fbcaSJoshua Felmeden const struct ens210_chip_info *chip_info; 83c524fbcaSJoshua Felmeden struct mutex lock; 84c524fbcaSJoshua Felmeden }; 85c524fbcaSJoshua Felmeden 86c524fbcaSJoshua Felmeden /* calculate 17-bit crc7 */ 87c524fbcaSJoshua Felmeden static u8 ens210_crc7(u32 val) 88c524fbcaSJoshua Felmeden { 89c524fbcaSJoshua Felmeden unsigned int val_be = (val & 0x1ffff) >> 0x8; 90c524fbcaSJoshua Felmeden 91c524fbcaSJoshua Felmeden return crc7_be(0xde, (u8 *)&val_be, 3) >> 1; 92c524fbcaSJoshua Felmeden } 93c524fbcaSJoshua Felmeden 94c524fbcaSJoshua Felmeden static int ens210_get_measurement(struct iio_dev *indio_dev, bool temp, int *val) 95c524fbcaSJoshua Felmeden { 96c524fbcaSJoshua Felmeden struct ens210_data *data = iio_priv(indio_dev); 97c524fbcaSJoshua Felmeden struct device *dev = &data->client->dev; 98c524fbcaSJoshua Felmeden u32 regval; 99c524fbcaSJoshua Felmeden u8 regval_le[3]; 100c524fbcaSJoshua Felmeden int ret; 101c524fbcaSJoshua Felmeden 102c524fbcaSJoshua Felmeden /* assert read */ 103c524fbcaSJoshua Felmeden ret = i2c_smbus_write_byte_data(data->client, ENS210_REG_SENS_START, 104c524fbcaSJoshua Felmeden temp ? ENS210_SENS_START_T_START : 105c524fbcaSJoshua Felmeden ENS210_SENS_START_H_START); 106c524fbcaSJoshua Felmeden if (ret) 107c524fbcaSJoshua Felmeden return ret; 108c524fbcaSJoshua Felmeden 109c524fbcaSJoshua Felmeden /* wait for conversion to be ready */ 110c524fbcaSJoshua Felmeden msleep(data->chip_info->conv_time_msec); 111c524fbcaSJoshua Felmeden 112c524fbcaSJoshua Felmeden ret = i2c_smbus_read_byte_data(data->client, ENS210_REG_SENS_STAT); 113c524fbcaSJoshua Felmeden if (ret < 0) 114c524fbcaSJoshua Felmeden return ret; 115c524fbcaSJoshua Felmeden 116c524fbcaSJoshua Felmeden /* perform read */ 117c524fbcaSJoshua Felmeden ret = i2c_smbus_read_i2c_block_data( 118c524fbcaSJoshua Felmeden data->client, temp ? ENS210_REG_T_VAL : ENS210_REG_H_VAL, 3, 119c524fbcaSJoshua Felmeden regval_le); 120c524fbcaSJoshua Felmeden if (ret < 0) { 121c524fbcaSJoshua Felmeden dev_err(dev, "failed to read register"); 122c524fbcaSJoshua Felmeden return -EIO; 123c524fbcaSJoshua Felmeden } 124c524fbcaSJoshua Felmeden if (ret != 3) { 125c524fbcaSJoshua Felmeden dev_err(dev, "expected 3 bytes, received %d\n", ret); 126c524fbcaSJoshua Felmeden return -EIO; 127c524fbcaSJoshua Felmeden } 128c524fbcaSJoshua Felmeden 129c524fbcaSJoshua Felmeden regval = get_unaligned_le24(regval_le); 130c524fbcaSJoshua Felmeden if (ens210_crc7(regval) != ((regval >> 17) & 0x7f)) { 131c524fbcaSJoshua Felmeden dev_err(dev, "invalid crc\n"); 132c524fbcaSJoshua Felmeden return -EIO; 133c524fbcaSJoshua Felmeden } 134c524fbcaSJoshua Felmeden 135c524fbcaSJoshua Felmeden if (!((regval >> 16) & 0x1)) { 136c524fbcaSJoshua Felmeden dev_err(dev, "data is not valid"); 137c524fbcaSJoshua Felmeden return -EIO; 138c524fbcaSJoshua Felmeden } 139c524fbcaSJoshua Felmeden 140c524fbcaSJoshua Felmeden *val = regval & GENMASK(15, 0); 141c524fbcaSJoshua Felmeden return IIO_VAL_INT; 142c524fbcaSJoshua Felmeden } 143c524fbcaSJoshua Felmeden 144c524fbcaSJoshua Felmeden static int ens210_read_raw(struct iio_dev *indio_dev, 145c524fbcaSJoshua Felmeden struct iio_chan_spec const *channel, int *val, 146c524fbcaSJoshua Felmeden int *val2, long mask) 147c524fbcaSJoshua Felmeden { 148c524fbcaSJoshua Felmeden struct ens210_data *data = iio_priv(indio_dev); 149c524fbcaSJoshua Felmeden int ret; 150c524fbcaSJoshua Felmeden 151c524fbcaSJoshua Felmeden switch (mask) { 152c524fbcaSJoshua Felmeden case IIO_CHAN_INFO_RAW: 153c524fbcaSJoshua Felmeden scoped_guard(mutex, &data->lock) { 154c524fbcaSJoshua Felmeden ret = ens210_get_measurement( 155c524fbcaSJoshua Felmeden indio_dev, channel->type == IIO_TEMP, val); 156c524fbcaSJoshua Felmeden if (ret) 157c524fbcaSJoshua Felmeden return ret; 158c524fbcaSJoshua Felmeden return IIO_VAL_INT; 159c524fbcaSJoshua Felmeden } 160c524fbcaSJoshua Felmeden return -EINVAL; /* compiler warning workaround */ 161c524fbcaSJoshua Felmeden case IIO_CHAN_INFO_SCALE: 162c524fbcaSJoshua Felmeden if (channel->type == IIO_TEMP) { 163c524fbcaSJoshua Felmeden *val = 15; 164c524fbcaSJoshua Felmeden *val2 = 625000; 165c524fbcaSJoshua Felmeden } else { 166c524fbcaSJoshua Felmeden *val = 1; 167c524fbcaSJoshua Felmeden *val2 = 953125; 168c524fbcaSJoshua Felmeden } 169c524fbcaSJoshua Felmeden return IIO_VAL_INT_PLUS_MICRO; 170c524fbcaSJoshua Felmeden case IIO_CHAN_INFO_OFFSET: 171c524fbcaSJoshua Felmeden *val = -17481; 172c524fbcaSJoshua Felmeden *val2 = 600000; 173c524fbcaSJoshua Felmeden return IIO_VAL_INT_PLUS_MICRO; 174c524fbcaSJoshua Felmeden default: 175c524fbcaSJoshua Felmeden return -EINVAL; 176c524fbcaSJoshua Felmeden } 177c524fbcaSJoshua Felmeden } 178c524fbcaSJoshua Felmeden 179c524fbcaSJoshua Felmeden static const struct iio_chan_spec ens210_channels[] = { 180c524fbcaSJoshua Felmeden { 181c524fbcaSJoshua Felmeden .type = IIO_TEMP, 182c524fbcaSJoshua Felmeden .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 183c524fbcaSJoshua Felmeden BIT(IIO_CHAN_INFO_SCALE) | 184c524fbcaSJoshua Felmeden BIT(IIO_CHAN_INFO_OFFSET), 185c524fbcaSJoshua Felmeden }, 186c524fbcaSJoshua Felmeden { 187c524fbcaSJoshua Felmeden .type = IIO_HUMIDITYRELATIVE, 188c524fbcaSJoshua Felmeden .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 189c524fbcaSJoshua Felmeden BIT(IIO_CHAN_INFO_SCALE), 190c524fbcaSJoshua Felmeden } 191c524fbcaSJoshua Felmeden }; 192c524fbcaSJoshua Felmeden 193c524fbcaSJoshua Felmeden static const struct iio_info ens210_info = { 194c524fbcaSJoshua Felmeden .read_raw = ens210_read_raw, 195c524fbcaSJoshua Felmeden }; 196c524fbcaSJoshua Felmeden 197c524fbcaSJoshua Felmeden static int ens210_probe(struct i2c_client *client) 198c524fbcaSJoshua Felmeden { 199c524fbcaSJoshua Felmeden struct ens210_data *data; 200c524fbcaSJoshua Felmeden struct iio_dev *indio_dev; 201c524fbcaSJoshua Felmeden uint16_t part_id; 202c524fbcaSJoshua Felmeden int ret; 203c524fbcaSJoshua Felmeden 204c524fbcaSJoshua Felmeden if (!i2c_check_functionality(client->adapter, 205c524fbcaSJoshua Felmeden I2C_FUNC_SMBUS_WRITE_BYTE_DATA | 206c524fbcaSJoshua Felmeden I2C_FUNC_SMBUS_WRITE_BYTE | 207c524fbcaSJoshua Felmeden I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 208c524fbcaSJoshua Felmeden return dev_err_probe(&client->dev, -EOPNOTSUPP, 209c524fbcaSJoshua Felmeden "adapter does not support some i2c transactions\n"); 210c524fbcaSJoshua Felmeden } 211c524fbcaSJoshua Felmeden 212c524fbcaSJoshua Felmeden indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 213c524fbcaSJoshua Felmeden if (!indio_dev) 214c524fbcaSJoshua Felmeden return -ENOMEM; 215c524fbcaSJoshua Felmeden 216c524fbcaSJoshua Felmeden data = iio_priv(indio_dev); 217c524fbcaSJoshua Felmeden data->client = client; 218c524fbcaSJoshua Felmeden mutex_init(&data->lock); 219c524fbcaSJoshua Felmeden data->chip_info = i2c_get_match_data(client); 220c524fbcaSJoshua Felmeden 221c524fbcaSJoshua Felmeden ret = devm_regulator_get_enable(&client->dev, "vdd"); 222c524fbcaSJoshua Felmeden if (ret) 223c524fbcaSJoshua Felmeden return ret; 224c524fbcaSJoshua Felmeden 225c524fbcaSJoshua Felmeden /* reset device */ 226c524fbcaSJoshua Felmeden ret = i2c_smbus_write_byte_data(client, ENS210_REG_SYS_CTRL, 227c524fbcaSJoshua Felmeden ENS210_SYS_CTRL_SYS_RESET); 228c524fbcaSJoshua Felmeden if (ret) 229c524fbcaSJoshua Felmeden return ret; 230c524fbcaSJoshua Felmeden 231c524fbcaSJoshua Felmeden /* wait for device to become active */ 232c524fbcaSJoshua Felmeden usleep_range(4000, 5000); 233c524fbcaSJoshua Felmeden 234c524fbcaSJoshua Felmeden /* disable low power mode */ 235c524fbcaSJoshua Felmeden ret = i2c_smbus_write_byte_data(client, ENS210_REG_SYS_CTRL, 0x00); 236c524fbcaSJoshua Felmeden if (ret) 237c524fbcaSJoshua Felmeden return ret; 238c524fbcaSJoshua Felmeden 239c524fbcaSJoshua Felmeden /* wait for device to finish */ 240c524fbcaSJoshua Felmeden usleep_range(4000, 5000); 241c524fbcaSJoshua Felmeden 242c524fbcaSJoshua Felmeden /* get part_id */ 243c524fbcaSJoshua Felmeden ret = i2c_smbus_read_word_data(client, ENS210_REG_PART_ID); 244c524fbcaSJoshua Felmeden if (ret < 0) 245c524fbcaSJoshua Felmeden return ret; 246c524fbcaSJoshua Felmeden part_id = ret; 247c524fbcaSJoshua Felmeden 248c524fbcaSJoshua Felmeden if (part_id != data->chip_info->part_id) { 249c524fbcaSJoshua Felmeden dev_info(&client->dev, 250c524fbcaSJoshua Felmeden "Part ID does not match (0x%04x != 0x%04x)\n", part_id, 251c524fbcaSJoshua Felmeden data->chip_info->part_id); 252c524fbcaSJoshua Felmeden } 253c524fbcaSJoshua Felmeden 254c524fbcaSJoshua Felmeden /* reenable low power */ 255c524fbcaSJoshua Felmeden ret = i2c_smbus_write_byte_data(client, ENS210_REG_SYS_CTRL, 256c524fbcaSJoshua Felmeden ENS210_SYS_CTRL_LOW_POWER_ENABLE); 257c524fbcaSJoshua Felmeden if (ret) 258c524fbcaSJoshua Felmeden return ret; 259c524fbcaSJoshua Felmeden 260c524fbcaSJoshua Felmeden indio_dev->name = data->chip_info->name; 261c524fbcaSJoshua Felmeden indio_dev->modes = INDIO_DIRECT_MODE; 262c524fbcaSJoshua Felmeden indio_dev->channels = ens210_channels; 263c524fbcaSJoshua Felmeden indio_dev->num_channels = ARRAY_SIZE(ens210_channels); 264c524fbcaSJoshua Felmeden indio_dev->info = &ens210_info; 265c524fbcaSJoshua Felmeden 266c524fbcaSJoshua Felmeden return devm_iio_device_register(&client->dev, indio_dev); 267c524fbcaSJoshua Felmeden } 268c524fbcaSJoshua Felmeden 269c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens210_chip_info_data = { 270c524fbcaSJoshua Felmeden .name = "ens210", 271c524fbcaSJoshua Felmeden .part_id = ENS210, 272c524fbcaSJoshua Felmeden .conv_time_msec = 130, 273c524fbcaSJoshua Felmeden }; 274c524fbcaSJoshua Felmeden 275c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens210a_chip_info_data = { 276c524fbcaSJoshua Felmeden .name = "ens210a", 277c524fbcaSJoshua Felmeden .part_id = ENS210A, 278c524fbcaSJoshua Felmeden .conv_time_msec = 130, 279c524fbcaSJoshua Felmeden }; 280c524fbcaSJoshua Felmeden 281c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens211_chip_info_data = { 282c524fbcaSJoshua Felmeden .name = "ens211", 283c524fbcaSJoshua Felmeden .part_id = ENS211, 284c524fbcaSJoshua Felmeden .conv_time_msec = 32, 285c524fbcaSJoshua Felmeden }; 286c524fbcaSJoshua Felmeden 287c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens212_chip_info_data = { 288c524fbcaSJoshua Felmeden .name = "ens212", 289c524fbcaSJoshua Felmeden .part_id = ENS212, 290c524fbcaSJoshua Felmeden .conv_time_msec = 32, 291c524fbcaSJoshua Felmeden }; 292c524fbcaSJoshua Felmeden 293c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens213a_chip_info_data = { 294c524fbcaSJoshua Felmeden .name = "ens213a", 295c524fbcaSJoshua Felmeden .part_id = ENS213A, 296c524fbcaSJoshua Felmeden .conv_time_msec = 130, 297c524fbcaSJoshua Felmeden }; 298c524fbcaSJoshua Felmeden 299c524fbcaSJoshua Felmeden static const struct ens210_chip_info ens215_chip_info_data = { 300c524fbcaSJoshua Felmeden .name = "ens215", 301c524fbcaSJoshua Felmeden .part_id = ENS215, 302c524fbcaSJoshua Felmeden .conv_time_msec = 130, 303c524fbcaSJoshua Felmeden }; 304c524fbcaSJoshua Felmeden 305c524fbcaSJoshua Felmeden static const struct of_device_id ens210_of_match[] = { 306c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens210", .data = &ens210_chip_info_data }, 307c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens210a", .data = &ens210a_chip_info_data }, 308c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens211", .data = &ens211_chip_info_data }, 309c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens212", .data = &ens212_chip_info_data }, 310c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens213a", .data = &ens213a_chip_info_data }, 311c524fbcaSJoshua Felmeden { .compatible = "sciosense,ens215", .data = &ens215_chip_info_data }, 312c524fbcaSJoshua Felmeden { } 313c524fbcaSJoshua Felmeden }; 314c524fbcaSJoshua Felmeden MODULE_DEVICE_TABLE(of, ens210_of_match); 315c524fbcaSJoshua Felmeden 316c524fbcaSJoshua Felmeden static const struct i2c_device_id ens210_id_table[] = { 317c524fbcaSJoshua Felmeden { "ens210", (kernel_ulong_t)&ens210_chip_info_data }, 318c524fbcaSJoshua Felmeden { "ens210a", (kernel_ulong_t)&ens210a_chip_info_data }, 319c524fbcaSJoshua Felmeden { "ens211", (kernel_ulong_t)&ens211_chip_info_data }, 320c524fbcaSJoshua Felmeden { "ens212", (kernel_ulong_t)&ens212_chip_info_data }, 321c524fbcaSJoshua Felmeden { "ens213a", (kernel_ulong_t)&ens213a_chip_info_data }, 322c524fbcaSJoshua Felmeden { "ens215", (kernel_ulong_t)&ens215_chip_info_data }, 323c524fbcaSJoshua Felmeden { } 324c524fbcaSJoshua Felmeden }; 325c524fbcaSJoshua Felmeden MODULE_DEVICE_TABLE(i2c, ens210_id_table); 326c524fbcaSJoshua Felmeden 327c524fbcaSJoshua Felmeden static struct i2c_driver ens210_driver = { 328c524fbcaSJoshua Felmeden .probe = ens210_probe, 329c524fbcaSJoshua Felmeden .id_table = ens210_id_table, 330c524fbcaSJoshua Felmeden .driver = { 331c524fbcaSJoshua Felmeden .name = "ens210", 332c524fbcaSJoshua Felmeden .of_match_table = ens210_of_match, 333c524fbcaSJoshua Felmeden }, 334c524fbcaSJoshua Felmeden }; 335c524fbcaSJoshua Felmeden module_i2c_driver(ens210_driver); 336c524fbcaSJoshua Felmeden 337c524fbcaSJoshua Felmeden MODULE_DESCRIPTION("ScioSense ENS210 temperature and humidity sensor driver"); 338c524fbcaSJoshua Felmeden MODULE_AUTHOR("Joshua Felmeden <jfelmeden@thegoodpenguin.co.uk>"); 339c524fbcaSJoshua Felmeden MODULE_LICENSE("GPL"); 340