xref: /linux/drivers/iio/humidity/hdc2010.c (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
10115a63cSEugene Zaikonnikov // SPDX-License-Identifier: GPL-2.0+
20115a63cSEugene Zaikonnikov /*
30115a63cSEugene Zaikonnikov  * hdc2010.c - Support for the TI HDC2010 and HDC2080
40115a63cSEugene Zaikonnikov  * temperature + relative humidity sensors
50115a63cSEugene Zaikonnikov  *
60115a63cSEugene Zaikonnikov  * Copyright (C) 2020 Norphonic AS
70115a63cSEugene Zaikonnikov  * Author: Eugene Zaikonnikov <ez@norphonic.com>
80115a63cSEugene Zaikonnikov  *
90115a63cSEugene Zaikonnikov  * Datasheet: https://www.ti.com/product/HDC2010/datasheet
100115a63cSEugene Zaikonnikov  * Datasheet: https://www.ti.com/product/HDC2080/datasheet
110115a63cSEugene Zaikonnikov  */
120115a63cSEugene Zaikonnikov 
130115a63cSEugene Zaikonnikov #include <linux/module.h>
140115a63cSEugene Zaikonnikov #include <linux/init.h>
150115a63cSEugene Zaikonnikov #include <linux/i2c.h>
160115a63cSEugene Zaikonnikov #include <linux/bitops.h>
170115a63cSEugene Zaikonnikov 
180115a63cSEugene Zaikonnikov #include <linux/iio/iio.h>
190115a63cSEugene Zaikonnikov #include <linux/iio/sysfs.h>
200115a63cSEugene Zaikonnikov 
210115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_LOW			0x00
220115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_HIGH			0x01
230115a63cSEugene Zaikonnikov #define HDC2010_REG_HUMIDITY_LOW		0x02
240115a63cSEugene Zaikonnikov #define HDC2010_REG_HUMIDITY_HIGH		0x03
250115a63cSEugene Zaikonnikov #define HDC2010_REG_INTERRUPT_DRDY		0x04
260115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_MAX			0x05
270115a63cSEugene Zaikonnikov #define HDC2010_REG_HUMIDITY_MAX		0x06
280115a63cSEugene Zaikonnikov #define HDC2010_REG_INTERRUPT_EN		0x07
290115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_OFFSET_ADJ		0x08
300115a63cSEugene Zaikonnikov #define HDC2010_REG_HUMIDITY_OFFSET_ADJ		0x09
310115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_THR_L			0x0a
320115a63cSEugene Zaikonnikov #define HDC2010_REG_TEMP_THR_H			0x0b
330115a63cSEugene Zaikonnikov #define HDC2010_REG_RH_THR_L			0x0c
340115a63cSEugene Zaikonnikov #define HDC2010_REG_RH_THR_H			0x0d
350115a63cSEugene Zaikonnikov #define HDC2010_REG_RESET_DRDY_INT_CONF		0x0e
360115a63cSEugene Zaikonnikov #define HDC2010_REG_MEASUREMENT_CONF		0x0f
370115a63cSEugene Zaikonnikov 
380115a63cSEugene Zaikonnikov #define HDC2010_MEAS_CONF			GENMASK(2, 1)
390115a63cSEugene Zaikonnikov #define HDC2010_MEAS_TRIG			BIT(0)
400115a63cSEugene Zaikonnikov #define HDC2010_HEATER_EN			BIT(3)
410115a63cSEugene Zaikonnikov #define HDC2010_AMM				GENMASK(6, 4)
420115a63cSEugene Zaikonnikov 
430115a63cSEugene Zaikonnikov struct hdc2010_data {
440115a63cSEugene Zaikonnikov 	struct i2c_client *client;
450115a63cSEugene Zaikonnikov 	struct mutex lock;
460115a63cSEugene Zaikonnikov 	u8 measurement_config;
470115a63cSEugene Zaikonnikov 	u8 interrupt_config;
480115a63cSEugene Zaikonnikov 	u8 drdy_config;
490115a63cSEugene Zaikonnikov };
500115a63cSEugene Zaikonnikov 
510115a63cSEugene Zaikonnikov enum hdc2010_addr_groups {
520115a63cSEugene Zaikonnikov 	HDC2010_GROUP_TEMP = 0,
530115a63cSEugene Zaikonnikov 	HDC2010_GROUP_HUMIDITY,
540115a63cSEugene Zaikonnikov };
550115a63cSEugene Zaikonnikov 
560115a63cSEugene Zaikonnikov struct hdc2010_reg_record {
570115a63cSEugene Zaikonnikov 	unsigned long primary;
580115a63cSEugene Zaikonnikov 	unsigned long peak;
590115a63cSEugene Zaikonnikov };
600115a63cSEugene Zaikonnikov 
610115a63cSEugene Zaikonnikov static const struct hdc2010_reg_record hdc2010_reg_translation[] = {
620115a63cSEugene Zaikonnikov 	[HDC2010_GROUP_TEMP] = {
630115a63cSEugene Zaikonnikov 		.primary = HDC2010_REG_TEMP_LOW,
640115a63cSEugene Zaikonnikov 		.peak = HDC2010_REG_TEMP_MAX,
650115a63cSEugene Zaikonnikov 	},
660115a63cSEugene Zaikonnikov 	[HDC2010_GROUP_HUMIDITY] = {
670115a63cSEugene Zaikonnikov 		.primary = HDC2010_REG_HUMIDITY_LOW,
680115a63cSEugene Zaikonnikov 		.peak = HDC2010_REG_HUMIDITY_MAX,
690115a63cSEugene Zaikonnikov 	},
700115a63cSEugene Zaikonnikov };
710115a63cSEugene Zaikonnikov 
720115a63cSEugene Zaikonnikov static IIO_CONST_ATTR(out_current_heater_raw_available, "0 1");
730115a63cSEugene Zaikonnikov 
740115a63cSEugene Zaikonnikov static struct attribute *hdc2010_attributes[] = {
750115a63cSEugene Zaikonnikov 	&iio_const_attr_out_current_heater_raw_available.dev_attr.attr,
760115a63cSEugene Zaikonnikov 	NULL
770115a63cSEugene Zaikonnikov };
780115a63cSEugene Zaikonnikov 
790115a63cSEugene Zaikonnikov static const struct attribute_group hdc2010_attribute_group = {
800115a63cSEugene Zaikonnikov 	.attrs = hdc2010_attributes,
810115a63cSEugene Zaikonnikov };
820115a63cSEugene Zaikonnikov 
830115a63cSEugene Zaikonnikov static const struct iio_chan_spec hdc2010_channels[] = {
840115a63cSEugene Zaikonnikov 	{
850115a63cSEugene Zaikonnikov 		.type = IIO_TEMP,
860115a63cSEugene Zaikonnikov 		.address = HDC2010_GROUP_TEMP,
870115a63cSEugene Zaikonnikov 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
880115a63cSEugene Zaikonnikov 			BIT(IIO_CHAN_INFO_PEAK) |
890115a63cSEugene Zaikonnikov 			BIT(IIO_CHAN_INFO_OFFSET) |
900115a63cSEugene Zaikonnikov 			BIT(IIO_CHAN_INFO_SCALE),
910115a63cSEugene Zaikonnikov 	},
920115a63cSEugene Zaikonnikov 	{
930115a63cSEugene Zaikonnikov 		.type = IIO_HUMIDITYRELATIVE,
940115a63cSEugene Zaikonnikov 		.address = HDC2010_GROUP_HUMIDITY,
950115a63cSEugene Zaikonnikov 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
960115a63cSEugene Zaikonnikov 			BIT(IIO_CHAN_INFO_PEAK) |
970115a63cSEugene Zaikonnikov 			BIT(IIO_CHAN_INFO_SCALE),
980115a63cSEugene Zaikonnikov 	},
990115a63cSEugene Zaikonnikov 	{
1000115a63cSEugene Zaikonnikov 		.type = IIO_CURRENT,
1010115a63cSEugene Zaikonnikov 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1020115a63cSEugene Zaikonnikov 		.extend_name = "heater",
1030115a63cSEugene Zaikonnikov 		.output = 1,
1040115a63cSEugene Zaikonnikov 	},
1050115a63cSEugene Zaikonnikov };
1060115a63cSEugene Zaikonnikov 
hdc2010_update_drdy_config(struct hdc2010_data * data,char mask,char val)1070115a63cSEugene Zaikonnikov static int hdc2010_update_drdy_config(struct hdc2010_data *data,
1080115a63cSEugene Zaikonnikov 					     char mask, char val)
1090115a63cSEugene Zaikonnikov {
1100115a63cSEugene Zaikonnikov 	u8 tmp = (~mask & data->drdy_config) | val;
1110115a63cSEugene Zaikonnikov 	int ret;
1120115a63cSEugene Zaikonnikov 
1130115a63cSEugene Zaikonnikov 	ret = i2c_smbus_write_byte_data(data->client,
1140115a63cSEugene Zaikonnikov 					HDC2010_REG_RESET_DRDY_INT_CONF, tmp);
1150115a63cSEugene Zaikonnikov 	if (ret)
1160115a63cSEugene Zaikonnikov 		return ret;
1170115a63cSEugene Zaikonnikov 
1180115a63cSEugene Zaikonnikov 	data->drdy_config = tmp;
1190115a63cSEugene Zaikonnikov 
1200115a63cSEugene Zaikonnikov 	return 0;
1210115a63cSEugene Zaikonnikov }
1220115a63cSEugene Zaikonnikov 
hdc2010_get_prim_measurement_word(struct hdc2010_data * data,struct iio_chan_spec const * chan)1230115a63cSEugene Zaikonnikov static int hdc2010_get_prim_measurement_word(struct hdc2010_data *data,
1240115a63cSEugene Zaikonnikov 					     struct iio_chan_spec const *chan)
1250115a63cSEugene Zaikonnikov {
1260115a63cSEugene Zaikonnikov 	struct i2c_client *client = data->client;
1270115a63cSEugene Zaikonnikov 	s32 ret;
1280115a63cSEugene Zaikonnikov 
1290115a63cSEugene Zaikonnikov 	ret = i2c_smbus_read_word_data(client,
1300115a63cSEugene Zaikonnikov 			hdc2010_reg_translation[chan->address].primary);
1310115a63cSEugene Zaikonnikov 
1320115a63cSEugene Zaikonnikov 	if (ret < 0)
1330115a63cSEugene Zaikonnikov 		dev_err(&client->dev, "Could not read sensor measurement word\n");
1340115a63cSEugene Zaikonnikov 
1350115a63cSEugene Zaikonnikov 	return ret;
1360115a63cSEugene Zaikonnikov }
1370115a63cSEugene Zaikonnikov 
hdc2010_get_peak_measurement_byte(struct hdc2010_data * data,struct iio_chan_spec const * chan)1380115a63cSEugene Zaikonnikov static int hdc2010_get_peak_measurement_byte(struct hdc2010_data *data,
1390115a63cSEugene Zaikonnikov 					     struct iio_chan_spec const *chan)
1400115a63cSEugene Zaikonnikov {
1410115a63cSEugene Zaikonnikov 	struct i2c_client *client = data->client;
1420115a63cSEugene Zaikonnikov 	s32 ret;
1430115a63cSEugene Zaikonnikov 
1440115a63cSEugene Zaikonnikov 	ret = i2c_smbus_read_byte_data(client,
1450115a63cSEugene Zaikonnikov 			hdc2010_reg_translation[chan->address].peak);
1460115a63cSEugene Zaikonnikov 
1470115a63cSEugene Zaikonnikov 	if (ret < 0)
1480115a63cSEugene Zaikonnikov 		dev_err(&client->dev, "Could not read sensor measurement byte\n");
1490115a63cSEugene Zaikonnikov 
1500115a63cSEugene Zaikonnikov 	return ret;
1510115a63cSEugene Zaikonnikov }
1520115a63cSEugene Zaikonnikov 
hdc2010_get_heater_status(struct hdc2010_data * data)1530115a63cSEugene Zaikonnikov static int hdc2010_get_heater_status(struct hdc2010_data *data)
1540115a63cSEugene Zaikonnikov {
1550115a63cSEugene Zaikonnikov 	return !!(data->drdy_config & HDC2010_HEATER_EN);
1560115a63cSEugene Zaikonnikov }
1570115a63cSEugene Zaikonnikov 
hdc2010_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)1580115a63cSEugene Zaikonnikov static int hdc2010_read_raw(struct iio_dev *indio_dev,
1590115a63cSEugene Zaikonnikov 			    struct iio_chan_spec const *chan, int *val,
1600115a63cSEugene Zaikonnikov 			    int *val2, long mask)
1610115a63cSEugene Zaikonnikov {
1620115a63cSEugene Zaikonnikov 	struct hdc2010_data *data = iio_priv(indio_dev);
1630115a63cSEugene Zaikonnikov 
1640115a63cSEugene Zaikonnikov 	switch (mask) {
1650115a63cSEugene Zaikonnikov 	case IIO_CHAN_INFO_RAW: {
1660115a63cSEugene Zaikonnikov 		int ret;
1670115a63cSEugene Zaikonnikov 
1680115a63cSEugene Zaikonnikov 		if (chan->type == IIO_CURRENT) {
1690115a63cSEugene Zaikonnikov 			*val = hdc2010_get_heater_status(data);
1700115a63cSEugene Zaikonnikov 			return IIO_VAL_INT;
1710115a63cSEugene Zaikonnikov 		}
1720115a63cSEugene Zaikonnikov 		ret = iio_device_claim_direct_mode(indio_dev);
1730115a63cSEugene Zaikonnikov 		if (ret)
1740115a63cSEugene Zaikonnikov 			return ret;
1750115a63cSEugene Zaikonnikov 		mutex_lock(&data->lock);
1760115a63cSEugene Zaikonnikov 		ret = hdc2010_get_prim_measurement_word(data, chan);
1770115a63cSEugene Zaikonnikov 		mutex_unlock(&data->lock);
1780115a63cSEugene Zaikonnikov 		iio_device_release_direct_mode(indio_dev);
1790115a63cSEugene Zaikonnikov 		if (ret < 0)
1800115a63cSEugene Zaikonnikov 			return ret;
1810115a63cSEugene Zaikonnikov 		*val = ret;
1820115a63cSEugene Zaikonnikov 		return IIO_VAL_INT;
1830115a63cSEugene Zaikonnikov 	}
1840115a63cSEugene Zaikonnikov 	case IIO_CHAN_INFO_PEAK: {
1850115a63cSEugene Zaikonnikov 		int ret;
1860115a63cSEugene Zaikonnikov 
1870115a63cSEugene Zaikonnikov 		ret = iio_device_claim_direct_mode(indio_dev);
1880115a63cSEugene Zaikonnikov 		if (ret)
1890115a63cSEugene Zaikonnikov 			return ret;
1900115a63cSEugene Zaikonnikov 		mutex_lock(&data->lock);
1910115a63cSEugene Zaikonnikov 		ret = hdc2010_get_peak_measurement_byte(data, chan);
1920115a63cSEugene Zaikonnikov 		mutex_unlock(&data->lock);
1930115a63cSEugene Zaikonnikov 		iio_device_release_direct_mode(indio_dev);
1940115a63cSEugene Zaikonnikov 		if (ret < 0)
1950115a63cSEugene Zaikonnikov 			return ret;
1960115a63cSEugene Zaikonnikov 		/* Scaling up the value so we can use same offset as RAW */
1970115a63cSEugene Zaikonnikov 		*val = ret * 256;
1980115a63cSEugene Zaikonnikov 		return IIO_VAL_INT;
1990115a63cSEugene Zaikonnikov 	}
2000115a63cSEugene Zaikonnikov 	case IIO_CHAN_INFO_SCALE:
2010115a63cSEugene Zaikonnikov 		*val2 = 65536;
2020115a63cSEugene Zaikonnikov 		if (chan->type == IIO_TEMP)
2030115a63cSEugene Zaikonnikov 			*val = 165000;
2040115a63cSEugene Zaikonnikov 		else
2050115a63cSEugene Zaikonnikov 			*val = 100000;
2060115a63cSEugene Zaikonnikov 		return IIO_VAL_FRACTIONAL;
2070115a63cSEugene Zaikonnikov 	case IIO_CHAN_INFO_OFFSET:
2080115a63cSEugene Zaikonnikov 		*val = -15887;
2090115a63cSEugene Zaikonnikov 		*val2 = 515151;
2100115a63cSEugene Zaikonnikov 		return IIO_VAL_INT_PLUS_MICRO;
2110115a63cSEugene Zaikonnikov 	default:
2120115a63cSEugene Zaikonnikov 		return -EINVAL;
2130115a63cSEugene Zaikonnikov 	}
2140115a63cSEugene Zaikonnikov }
2150115a63cSEugene Zaikonnikov 
hdc2010_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)2160115a63cSEugene Zaikonnikov static int hdc2010_write_raw(struct iio_dev *indio_dev,
2170115a63cSEugene Zaikonnikov 			     struct iio_chan_spec const *chan,
2180115a63cSEugene Zaikonnikov 			     int val, int val2, long mask)
2190115a63cSEugene Zaikonnikov {
2200115a63cSEugene Zaikonnikov 	struct hdc2010_data *data = iio_priv(indio_dev);
2210115a63cSEugene Zaikonnikov 	int new, ret;
2220115a63cSEugene Zaikonnikov 
2230115a63cSEugene Zaikonnikov 	switch (mask) {
2240115a63cSEugene Zaikonnikov 	case IIO_CHAN_INFO_RAW:
2250115a63cSEugene Zaikonnikov 		if (chan->type != IIO_CURRENT || val2 != 0)
2260115a63cSEugene Zaikonnikov 			return -EINVAL;
2270115a63cSEugene Zaikonnikov 
2280115a63cSEugene Zaikonnikov 		switch (val) {
2290115a63cSEugene Zaikonnikov 		case 1:
2300115a63cSEugene Zaikonnikov 			new = HDC2010_HEATER_EN;
2310115a63cSEugene Zaikonnikov 			break;
2320115a63cSEugene Zaikonnikov 		case 0:
2330115a63cSEugene Zaikonnikov 			new = 0;
2340115a63cSEugene Zaikonnikov 			break;
2350115a63cSEugene Zaikonnikov 		default:
2360115a63cSEugene Zaikonnikov 			return -EINVAL;
2370115a63cSEugene Zaikonnikov 		}
2380115a63cSEugene Zaikonnikov 
2390115a63cSEugene Zaikonnikov 		mutex_lock(&data->lock);
2400115a63cSEugene Zaikonnikov 		ret = hdc2010_update_drdy_config(data, HDC2010_HEATER_EN, new);
2410115a63cSEugene Zaikonnikov 		mutex_unlock(&data->lock);
2420115a63cSEugene Zaikonnikov 		return ret;
2430115a63cSEugene Zaikonnikov 	default:
2440115a63cSEugene Zaikonnikov 		return -EINVAL;
2450115a63cSEugene Zaikonnikov 	}
2460115a63cSEugene Zaikonnikov }
2470115a63cSEugene Zaikonnikov 
2480115a63cSEugene Zaikonnikov static const struct iio_info hdc2010_info = {
2490115a63cSEugene Zaikonnikov 	.read_raw = hdc2010_read_raw,
2500115a63cSEugene Zaikonnikov 	.write_raw = hdc2010_write_raw,
2510115a63cSEugene Zaikonnikov 	.attrs = &hdc2010_attribute_group,
2520115a63cSEugene Zaikonnikov };
2530115a63cSEugene Zaikonnikov 
hdc2010_probe(struct i2c_client * client)2540a78deebSUwe Kleine-König static int hdc2010_probe(struct i2c_client *client)
2550115a63cSEugene Zaikonnikov {
2560115a63cSEugene Zaikonnikov 	struct iio_dev *indio_dev;
2570115a63cSEugene Zaikonnikov 	struct hdc2010_data *data;
2580115a63cSEugene Zaikonnikov 	u8 tmp;
2590115a63cSEugene Zaikonnikov 	int ret;
2600115a63cSEugene Zaikonnikov 
2610115a63cSEugene Zaikonnikov 	if (!i2c_check_functionality(client->adapter,
2620115a63cSEugene Zaikonnikov 	    I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
2630115a63cSEugene Zaikonnikov 		return -EOPNOTSUPP;
2640115a63cSEugene Zaikonnikov 
2650115a63cSEugene Zaikonnikov 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
2660115a63cSEugene Zaikonnikov 	if (!indio_dev)
2670115a63cSEugene Zaikonnikov 		return -ENOMEM;
2680115a63cSEugene Zaikonnikov 
2690115a63cSEugene Zaikonnikov 	data = iio_priv(indio_dev);
2700115a63cSEugene Zaikonnikov 	i2c_set_clientdata(client, indio_dev);
2710115a63cSEugene Zaikonnikov 	data->client = client;
2720115a63cSEugene Zaikonnikov 	mutex_init(&data->lock);
2730115a63cSEugene Zaikonnikov 
2740115a63cSEugene Zaikonnikov 	/*
2750115a63cSEugene Zaikonnikov 	 * As DEVICE ID register does not differentiate between
2760115a63cSEugene Zaikonnikov 	 * HDC2010 and HDC2080, we have the name hardcoded
2770115a63cSEugene Zaikonnikov 	 */
2780115a63cSEugene Zaikonnikov 	indio_dev->name = "hdc2010";
2790115a63cSEugene Zaikonnikov 	indio_dev->modes = INDIO_DIRECT_MODE;
2800115a63cSEugene Zaikonnikov 	indio_dev->info = &hdc2010_info;
2810115a63cSEugene Zaikonnikov 
2820115a63cSEugene Zaikonnikov 	indio_dev->channels = hdc2010_channels;
2830115a63cSEugene Zaikonnikov 	indio_dev->num_channels = ARRAY_SIZE(hdc2010_channels);
2840115a63cSEugene Zaikonnikov 
2850115a63cSEugene Zaikonnikov 	/* Enable Automatic Measurement Mode at 5Hz */
2860115a63cSEugene Zaikonnikov 	ret = hdc2010_update_drdy_config(data, HDC2010_AMM, HDC2010_AMM);
2870115a63cSEugene Zaikonnikov 	if (ret)
2880115a63cSEugene Zaikonnikov 		return ret;
2890115a63cSEugene Zaikonnikov 
2900115a63cSEugene Zaikonnikov 	/*
2910115a63cSEugene Zaikonnikov 	 * We enable both temp and humidity measurement.
2920115a63cSEugene Zaikonnikov 	 * However the measurement won't start even in AMM until triggered.
2930115a63cSEugene Zaikonnikov 	 */
2940115a63cSEugene Zaikonnikov 	tmp = (data->measurement_config & ~HDC2010_MEAS_CONF) |
2950115a63cSEugene Zaikonnikov 		HDC2010_MEAS_TRIG;
2960115a63cSEugene Zaikonnikov 
2970115a63cSEugene Zaikonnikov 	ret = i2c_smbus_write_byte_data(client, HDC2010_REG_MEASUREMENT_CONF, tmp);
2980115a63cSEugene Zaikonnikov 	if (ret) {
2990115a63cSEugene Zaikonnikov 		dev_warn(&client->dev, "Unable to set up measurement\n");
3000115a63cSEugene Zaikonnikov 		if (hdc2010_update_drdy_config(data, HDC2010_AMM, 0))
3010115a63cSEugene Zaikonnikov 			dev_warn(&client->dev, "Unable to restore default AMM\n");
3020115a63cSEugene Zaikonnikov 		return ret;
3032f0472a1Skernel test robot 	}
3040115a63cSEugene Zaikonnikov 
3050115a63cSEugene Zaikonnikov 	data->measurement_config = tmp;
3060115a63cSEugene Zaikonnikov 
3070115a63cSEugene Zaikonnikov 	return iio_device_register(indio_dev);
3080115a63cSEugene Zaikonnikov }
3090115a63cSEugene Zaikonnikov 
hdc2010_remove(struct i2c_client * client)310ed5c2f5fSUwe Kleine-König static void hdc2010_remove(struct i2c_client *client)
3110115a63cSEugene Zaikonnikov {
3120115a63cSEugene Zaikonnikov 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
3130115a63cSEugene Zaikonnikov 	struct hdc2010_data *data = iio_priv(indio_dev);
3140115a63cSEugene Zaikonnikov 
3150115a63cSEugene Zaikonnikov 	iio_device_unregister(indio_dev);
3160115a63cSEugene Zaikonnikov 
3170115a63cSEugene Zaikonnikov 	/* Disable Automatic Measurement Mode */
3180115a63cSEugene Zaikonnikov 	if (hdc2010_update_drdy_config(data, HDC2010_AMM, 0))
3190115a63cSEugene Zaikonnikov 		dev_warn(&client->dev, "Unable to restore default AMM\n");
3200115a63cSEugene Zaikonnikov }
3210115a63cSEugene Zaikonnikov 
3220115a63cSEugene Zaikonnikov static const struct i2c_device_id hdc2010_id[] = {
3230115a63cSEugene Zaikonnikov 	{ "hdc2010" },
3240115a63cSEugene Zaikonnikov 	{ "hdc2080" },
3250115a63cSEugene Zaikonnikov 	{ }
3260115a63cSEugene Zaikonnikov };
3270115a63cSEugene Zaikonnikov MODULE_DEVICE_TABLE(i2c, hdc2010_id);
3280115a63cSEugene Zaikonnikov 
3290115a63cSEugene Zaikonnikov static const struct of_device_id hdc2010_dt_ids[] = {
3300115a63cSEugene Zaikonnikov 	{ .compatible = "ti,hdc2010" },
3310115a63cSEugene Zaikonnikov 	{ .compatible = "ti,hdc2080" },
3320115a63cSEugene Zaikonnikov 	{ }
3330115a63cSEugene Zaikonnikov };
3340115a63cSEugene Zaikonnikov MODULE_DEVICE_TABLE(of, hdc2010_dt_ids);
3350115a63cSEugene Zaikonnikov 
3360115a63cSEugene Zaikonnikov static struct i2c_driver hdc2010_driver = {
3370115a63cSEugene Zaikonnikov 	.driver = {
3380115a63cSEugene Zaikonnikov 		.name	= "hdc2010",
3390115a63cSEugene Zaikonnikov 		.of_match_table = hdc2010_dt_ids,
3400115a63cSEugene Zaikonnikov 	},
341*7cf15f42SUwe Kleine-König 	.probe = hdc2010_probe,
3420115a63cSEugene Zaikonnikov 	.remove = hdc2010_remove,
3430115a63cSEugene Zaikonnikov 	.id_table = hdc2010_id,
3440115a63cSEugene Zaikonnikov };
3450115a63cSEugene Zaikonnikov module_i2c_driver(hdc2010_driver);
3460115a63cSEugene Zaikonnikov 
3470115a63cSEugene Zaikonnikov MODULE_AUTHOR("Eugene Zaikonnikov <ez@norphonic.com>");
3480115a63cSEugene Zaikonnikov MODULE_DESCRIPTION("TI HDC2010 humidity and temperature sensor driver");
3490115a63cSEugene Zaikonnikov MODULE_LICENSE("GPL");
350