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