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 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 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 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 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 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 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 254*0a78deebSUwe 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 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*0a78deebSUwe Kleine-König .probe_new = 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