812 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * cc2.c - Support for the Amphenol ChipCap 2 relative humidity, temperature sensor4 *5 * Part numbers supported:6 * CC2D23, CC2D23S, CC2D25, CC2D25S, CC2D33, CC2D33S, CC2D35, CC2D35S7 *8 * Author: Javier Carrasco <javier.carrasco.cruz@gmail.com>9 *10 * Datasheet and application notes:11 * https://www.amphenol-sensors.com/en/telaire/humidity/527-humidity-sensors/3095-chipcap-212 */13 14#include <linux/bitfield.h>15#include <linux/bits.h>16#include <linux/completion.h>17#include <linux/delay.h>18#include <linux/hwmon.h>19#include <linux/i2c.h>20#include <linux/interrupt.h>21#include <linux/irq.h>22#include <linux/module.h>23#include <linux/regulator/consumer.h>24 25#define CC2_START_CM 0xA026#define CC2_START_NOM 0x8027#define CC2_R_ALARM_H_ON 0x1828#define CC2_R_ALARM_H_OFF 0x1929#define CC2_R_ALARM_L_ON 0x1A30#define CC2_R_ALARM_L_OFF 0x1B31#define CC2_RW_OFFSET 0x4032#define CC2_W_ALARM_H_ON (CC2_R_ALARM_H_ON + CC2_RW_OFFSET)33#define CC2_W_ALARM_H_OFF (CC2_R_ALARM_H_OFF + CC2_RW_OFFSET)34#define CC2_W_ALARM_L_ON (CC2_R_ALARM_L_ON + CC2_RW_OFFSET)35#define CC2_W_ALARM_L_OFF (CC2_R_ALARM_L_OFF + CC2_RW_OFFSET)36 37#define CC2_STATUS_FIELD GENMASK(7, 6)38#define CC2_STATUS_VALID_DATA 0x0039#define CC2_STATUS_STALE_DATA 0x0140#define CC2_STATUS_CMD_MODE 0x0241 42#define CC2_RESPONSE_FIELD GENMASK(1, 0)43#define CC2_RESPONSE_BUSY 0x0044#define CC2_RESPONSE_ACK 0x0145#define CC2_RESPONSE_NACK 0x0246 47#define CC2_ERR_CORR_EEPROM BIT(2)48#define CC2_ERR_UNCORR_EEPROM BIT(3)49#define CC2_ERR_RAM_PARITY BIT(4)50#define CC2_ERR_CONFIG_LOAD BIT(5)51 52#define CC2_EEPROM_SIZE 1053#define CC2_EEPROM_DATA_LEN 354#define CC2_MEASUREMENT_DATA_LEN 455 56#define CC2_RH_DATA_FIELD GENMASK(13, 0)57 58/* ensure clean off -> on transitions */59#define CC2_POWER_CYCLE_MS 8060 61#define CC2_STARTUP_TO_DATA_MS 5562#define CC2_RESP_START_CM_US 10063#define CC2_RESP_EEPROM_R_US 10064#define CC2_RESP_EEPROM_W_MS 1265#define CC2_STARTUP_TIME_US 125066 67#define CC2_RH_MAX (100 * 1000U)68 69#define CC2_CM_RETRIES 570 71struct cc2_rh_alarm_info {72 bool low_alarm;73 bool high_alarm;74 bool low_alarm_visible;75 bool high_alarm_visible;76};77 78struct cc2_data {79 struct cc2_rh_alarm_info rh_alarm;80 struct completion complete;81 struct device *hwmon;82 struct i2c_client *client;83 struct mutex dev_access_lock; /* device access lock */84 struct regulator *regulator;85 const char *name;86 int irq_ready;87 int irq_low;88 int irq_high;89 bool process_irqs;90};91 92enum cc2_chan_addr {93 CC2_CHAN_TEMP = 0,94 CC2_CHAN_HUMIDITY,95};96 97/* %RH as a per cent mille from a register value */98static long cc2_rh_convert(u16 data)99{100 unsigned long tmp = (data & CC2_RH_DATA_FIELD) * CC2_RH_MAX;101 102 return tmp / ((1 << 14) - 1);103}104 105/* convert %RH to a register value */106static u16 cc2_rh_to_reg(long data)107{108 return data * ((1 << 14) - 1) / CC2_RH_MAX;109}110 111/* temperature in milli degrees celsius from a register value */112static long cc2_temp_convert(u16 data)113{114 unsigned long tmp = ((data >> 2) * 165 * 1000U) / ((1 << 14) - 1);115 116 return tmp - 40 * 1000U;117}118 119static int cc2_enable(struct cc2_data *data)120{121 int ret;122 123 /* exclusive regulator, check in case a disable failed */124 if (regulator_is_enabled(data->regulator))125 return 0;126 127 /* clear any pending completion */128 try_wait_for_completion(&data->complete);129 130 ret = regulator_enable(data->regulator);131 if (ret < 0)132 return ret;133 134 usleep_range(CC2_STARTUP_TIME_US, CC2_STARTUP_TIME_US + 125);135 136 data->process_irqs = true;137 138 return 0;139}140 141static void cc2_disable(struct cc2_data *data)142{143 int err;144 145 /* ignore alarms triggered by voltage toggling when powering up */146 data->process_irqs = false;147 148 /* exclusive regulator, check in case an enable failed */149 if (regulator_is_enabled(data->regulator)) {150 err = regulator_disable(data->regulator);151 if (err)152 dev_dbg(&data->client->dev, "Failed to disable device");153 }154}155 156static int cc2_cmd_response_diagnostic(struct device *dev, u8 status)157{158 int resp;159 160 if (FIELD_GET(CC2_STATUS_FIELD, status) != CC2_STATUS_CMD_MODE) {161 dev_dbg(dev, "Command sent out of command window\n");162 return -ETIMEDOUT;163 }164 165 resp = FIELD_GET(CC2_RESPONSE_FIELD, status);166 switch (resp) {167 case CC2_RESPONSE_ACK:168 return 0;169 case CC2_RESPONSE_BUSY:170 return -EBUSY;171 case CC2_RESPONSE_NACK:172 if (resp & CC2_ERR_CORR_EEPROM)173 dev_dbg(dev, "Command failed: corrected EEPROM\n");174 if (resp & CC2_ERR_UNCORR_EEPROM)175 dev_dbg(dev, "Command failed: uncorrected EEPROM\n");176 if (resp & CC2_ERR_RAM_PARITY)177 dev_dbg(dev, "Command failed: RAM parity\n");178 if (resp & CC2_ERR_RAM_PARITY)179 dev_dbg(dev, "Command failed: configuration error\n");180 return -ENODATA;181 default:182 dev_dbg(dev, "Unknown command reply\n");183 return -EINVAL;184 }185}186 187static int cc2_read_command_status(struct i2c_client *client)188{189 u8 status;190 int ret;191 192 ret = i2c_master_recv(client, &status, 1);193 if (ret != 1) {194 ret = ret < 0 ? ret : -EIO;195 return ret;196 }197 198 return cc2_cmd_response_diagnostic(&client->dev, status);199}200 201/*202 * The command mode is only accessible after sending the START_CM command in the203 * first 10 ms after power-up. Only in case the command window is missed,204 * CC2_CM_RETRIES retries are attempted before giving up and returning an error.205 */206static int cc2_command_mode_start(struct cc2_data *data)207{208 unsigned long timeout;209 int i, ret;210 211 for (i = 0; i < CC2_CM_RETRIES; i++) {212 ret = cc2_enable(data);213 if (ret < 0)214 return ret;215 216 ret = i2c_smbus_write_word_data(data->client, CC2_START_CM, 0);217 if (ret < 0)218 return ret;219 220 if (data->irq_ready > 0) {221 timeout = usecs_to_jiffies(2 * CC2_RESP_START_CM_US);222 ret = wait_for_completion_timeout(&data->complete,223 timeout);224 if (!ret)225 return -ETIMEDOUT;226 } else {227 usleep_range(CC2_RESP_START_CM_US,228 2 * CC2_RESP_START_CM_US);229 }230 ret = cc2_read_command_status(data->client);231 if (ret != -ETIMEDOUT || i == CC2_CM_RETRIES)232 break;233 234 /* command window missed, prepare for a retry */235 cc2_disable(data);236 msleep(CC2_POWER_CYCLE_MS);237 }238 239 return ret;240}241 242/* Sending a Start_NOM command finishes the command mode immediately with no243 * reply and the device enters normal operation mode244 */245static int cc2_command_mode_finish(struct cc2_data *data)246{247 int ret;248 249 ret = i2c_smbus_write_word_data(data->client, CC2_START_NOM, 0);250 if (ret < 0)251 return ret;252 253 return 0;254}255 256static int cc2_write_reg(struct cc2_data *data, u8 reg, u16 val)257{258 unsigned long timeout;259 int ret;260 261 ret = cc2_command_mode_start(data);262 if (ret < 0)263 goto disable;264 265 cpu_to_be16s(&val);266 ret = i2c_smbus_write_word_data(data->client, reg, val);267 if (ret < 0)268 goto disable;269 270 if (data->irq_ready > 0) {271 timeout = msecs_to_jiffies(2 * CC2_RESP_EEPROM_W_MS);272 ret = wait_for_completion_timeout(&data->complete, timeout);273 if (!ret) {274 ret = -ETIMEDOUT;275 goto disable;276 }277 } else {278 msleep(CC2_RESP_EEPROM_W_MS);279 }280 281 ret = cc2_read_command_status(data->client);282 283disable:284 cc2_disable(data);285 286 return ret;287}288 289static int cc2_read_reg(struct cc2_data *data, u8 reg, u16 *val)290{291 u8 buf[CC2_EEPROM_DATA_LEN];292 unsigned long timeout;293 int ret;294 295 ret = cc2_command_mode_start(data);296 if (ret < 0)297 return ret;298 299 ret = i2c_smbus_write_word_data(data->client, reg, 0);300 if (ret < 0)301 return ret;302 303 if (data->irq_ready > 0) {304 timeout = usecs_to_jiffies(2 * CC2_RESP_EEPROM_R_US);305 ret = wait_for_completion_timeout(&data->complete, timeout);306 if (!ret)307 return -ETIMEDOUT;308 309 } else {310 usleep_range(CC2_RESP_EEPROM_R_US, CC2_RESP_EEPROM_R_US + 10);311 }312 ret = i2c_master_recv(data->client, buf, CC2_EEPROM_DATA_LEN);313 if (ret != CC2_EEPROM_DATA_LEN)314 return ret < 0 ? ret : -EIO;315 316 *val = be16_to_cpup((__be16 *)&buf[1]);317 318 return cc2_read_command_status(data->client);319}320 321static int cc2_get_reg_val(struct cc2_data *data, u8 reg, long *val)322{323 u16 reg_val;324 int ret;325 326 ret = cc2_read_reg(data, reg, ®_val);327 if (!ret)328 *val = cc2_rh_convert(reg_val);329 330 cc2_disable(data);331 332 return ret;333}334 335static int cc2_data_fetch(struct i2c_client *client,336 enum hwmon_sensor_types type, long *val)337{338 u8 data[CC2_MEASUREMENT_DATA_LEN];339 u8 status;340 int ret;341 342 ret = i2c_master_recv(client, data, CC2_MEASUREMENT_DATA_LEN);343 if (ret != CC2_MEASUREMENT_DATA_LEN) {344 ret = ret < 0 ? ret : -EIO;345 return ret;346 }347 status = FIELD_GET(CC2_STATUS_FIELD, data[0]);348 if (status == CC2_STATUS_STALE_DATA)349 return -EBUSY;350 351 if (status != CC2_STATUS_VALID_DATA)352 return -EIO;353 354 switch (type) {355 case hwmon_humidity:356 *val = cc2_rh_convert(be16_to_cpup((__be16 *)&data[0]));357 break;358 case hwmon_temp:359 *val = cc2_temp_convert(be16_to_cpup((__be16 *)&data[2]));360 break;361 default:362 return -EINVAL;363 }364 365 return 0;366}367 368static int cc2_read_measurement(struct cc2_data *data,369 enum hwmon_sensor_types type, long *val)370{371 unsigned long timeout;372 int ret;373 374 if (data->irq_ready > 0) {375 timeout = msecs_to_jiffies(CC2_STARTUP_TO_DATA_MS * 2);376 ret = wait_for_completion_timeout(&data->complete, timeout);377 if (!ret)378 return -ETIMEDOUT;379 380 } else {381 msleep(CC2_STARTUP_TO_DATA_MS);382 }383 384 ret = cc2_data_fetch(data->client, type, val);385 386 return ret;387}388 389/*390 * A measurement requires enabling the device, waiting for the automatic391 * measurement to finish, reading the measurement data and disabling the device392 * again.393 */394static int cc2_measurement(struct cc2_data *data, enum hwmon_sensor_types type,395 long *val)396{397 int ret;398 399 ret = cc2_enable(data);400 if (ret)401 return ret;402 403 ret = cc2_read_measurement(data, type, val);404 405 cc2_disable(data);406 407 return ret;408}409 410/*411 * In order to check alarm status, the corresponding ALARM_OFF (hysteresis)412 * register must be read and a new measurement must be carried out to trigger413 * the alarm signals. Given that the device carries out a measurement after414 * exiting the command mode, there is no need to force two power-up sequences.415 * Instead, a NOM command is sent and the device is disabled after the416 * measurement is read.417 */418static int cc2_read_hyst_and_measure(struct cc2_data *data, u8 reg,419 long *hyst, long *measurement)420{421 u16 reg_val;422 int ret;423 424 ret = cc2_read_reg(data, reg, ®_val);425 if (ret)426 goto disable;427 428 *hyst = cc2_rh_convert(reg_val);429 430 ret = cc2_command_mode_finish(data);431 if (ret)432 goto disable;433 434 ret = cc2_read_measurement(data, hwmon_humidity, measurement);435 436disable:437 cc2_disable(data);438 439 return ret;440}441 442static umode_t cc2_is_visible(const void *data, enum hwmon_sensor_types type,443 u32 attr, int channel)444{445 const struct cc2_data *cc2 = data;446 447 switch (type) {448 case hwmon_humidity:449 switch (attr) {450 case hwmon_humidity_input:451 return 0444;452 case hwmon_humidity_min_alarm:453 return cc2->rh_alarm.low_alarm_visible ? 0444 : 0;454 case hwmon_humidity_max_alarm:455 return cc2->rh_alarm.high_alarm_visible ? 0444 : 0;456 case hwmon_humidity_min:457 case hwmon_humidity_min_hyst:458 return cc2->rh_alarm.low_alarm_visible ? 0644 : 0;459 case hwmon_humidity_max:460 case hwmon_humidity_max_hyst:461 return cc2->rh_alarm.high_alarm_visible ? 0644 : 0;462 default:463 return 0;464 }465 case hwmon_temp:466 switch (attr) {467 case hwmon_temp_input:468 return 0444;469 default:470 return 0;471 }472 default:473 break;474 }475 476 return 0;477}478 479static irqreturn_t cc2_ready_interrupt(int irq, void *data)480{481 struct cc2_data *cc2 = data;482 483 if (cc2->process_irqs)484 complete(&cc2->complete);485 486 return IRQ_HANDLED;487}488 489static irqreturn_t cc2_low_interrupt(int irq, void *data)490{491 struct cc2_data *cc2 = data;492 493 if (cc2->process_irqs) {494 hwmon_notify_event(cc2->hwmon, hwmon_humidity,495 hwmon_humidity_min_alarm, CC2_CHAN_HUMIDITY);496 cc2->rh_alarm.low_alarm = true;497 }498 499 return IRQ_HANDLED;500}501 502static irqreturn_t cc2_high_interrupt(int irq, void *data)503{504 struct cc2_data *cc2 = data;505 506 if (cc2->process_irqs) {507 hwmon_notify_event(cc2->hwmon, hwmon_humidity,508 hwmon_humidity_max_alarm, CC2_CHAN_HUMIDITY);509 cc2->rh_alarm.high_alarm = true;510 }511 512 return IRQ_HANDLED;513}514 515static int cc2_humidity_min_alarm_status(struct cc2_data *data, long *val)516{517 long measurement, min_hyst;518 int ret;519 520 ret = cc2_read_hyst_and_measure(data, CC2_R_ALARM_L_OFF, &min_hyst,521 &measurement);522 if (ret < 0)523 return ret;524 525 if (data->rh_alarm.low_alarm) {526 *val = (measurement < min_hyst) ? 1 : 0;527 data->rh_alarm.low_alarm = *val;528 } else {529 *val = 0;530 }531 532 return 0;533}534 535static int cc2_humidity_max_alarm_status(struct cc2_data *data, long *val)536{537 long measurement, max_hyst;538 int ret;539 540 ret = cc2_read_hyst_and_measure(data, CC2_R_ALARM_H_OFF, &max_hyst,541 &measurement);542 if (ret < 0)543 return ret;544 545 if (data->rh_alarm.high_alarm) {546 *val = (measurement > max_hyst) ? 1 : 0;547 data->rh_alarm.high_alarm = *val;548 } else {549 *val = 0;550 }551 552 return 0;553}554 555static int cc2_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,556 int channel, long *val)557{558 struct cc2_data *data = dev_get_drvdata(dev);559 int ret = 0;560 561 mutex_lock(&data->dev_access_lock);562 563 switch (type) {564 case hwmon_temp:565 ret = cc2_measurement(data, type, val);566 break;567 case hwmon_humidity:568 switch (attr) {569 case hwmon_humidity_input:570 ret = cc2_measurement(data, type, val);571 break;572 case hwmon_humidity_min:573 ret = cc2_get_reg_val(data, CC2_R_ALARM_L_ON, val);574 break;575 case hwmon_humidity_min_hyst:576 ret = cc2_get_reg_val(data, CC2_R_ALARM_L_OFF, val);577 break;578 case hwmon_humidity_max:579 ret = cc2_get_reg_val(data, CC2_R_ALARM_H_ON, val);580 break;581 case hwmon_humidity_max_hyst:582 ret = cc2_get_reg_val(data, CC2_R_ALARM_H_OFF, val);583 break;584 case hwmon_humidity_min_alarm:585 ret = cc2_humidity_min_alarm_status(data, val);586 break;587 case hwmon_humidity_max_alarm:588 ret = cc2_humidity_max_alarm_status(data, val);589 break;590 default:591 ret = -EOPNOTSUPP;592 }593 break;594 default:595 ret = -EOPNOTSUPP;596 }597 598 mutex_unlock(&data->dev_access_lock);599 600 return ret;601}602 603static int cc2_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,604 int channel, long val)605{606 struct cc2_data *data = dev_get_drvdata(dev);607 int ret;608 u16 arg;609 u8 cmd;610 611 if (type != hwmon_humidity)612 return -EOPNOTSUPP;613 614 if (val < 0 || val > CC2_RH_MAX)615 return -EINVAL;616 617 mutex_lock(&data->dev_access_lock);618 619 switch (attr) {620 case hwmon_humidity_min:621 cmd = CC2_W_ALARM_L_ON;622 arg = cc2_rh_to_reg(val);623 ret = cc2_write_reg(data, cmd, arg);624 break;625 626 case hwmon_humidity_min_hyst:627 cmd = CC2_W_ALARM_L_OFF;628 arg = cc2_rh_to_reg(val);629 ret = cc2_write_reg(data, cmd, arg);630 break;631 632 case hwmon_humidity_max:633 cmd = CC2_W_ALARM_H_ON;634 arg = cc2_rh_to_reg(val);635 ret = cc2_write_reg(data, cmd, arg);636 break;637 638 case hwmon_humidity_max_hyst:639 cmd = CC2_W_ALARM_H_OFF;640 arg = cc2_rh_to_reg(val);641 ret = cc2_write_reg(data, cmd, arg);642 break;643 644 default:645 ret = -EOPNOTSUPP;646 break;647 }648 649 mutex_unlock(&data->dev_access_lock);650 651 return ret;652}653 654static int cc2_request_ready_irq(struct cc2_data *data, struct device *dev)655{656 int ret = 0;657 658 data->irq_ready = fwnode_irq_get_byname(dev_fwnode(dev), "ready");659 if (data->irq_ready > 0) {660 init_completion(&data->complete);661 ret = devm_request_threaded_irq(dev, data->irq_ready, NULL,662 cc2_ready_interrupt,663 IRQF_ONESHOT |664 IRQF_TRIGGER_RISING,665 dev_name(dev), data);666 }667 668 return ret;669}670 671static int cc2_request_alarm_irqs(struct cc2_data *data, struct device *dev)672{673 int ret = 0;674 675 data->irq_low = fwnode_irq_get_byname(dev_fwnode(dev), "low");676 if (data->irq_low > 0) {677 ret = devm_request_threaded_irq(dev, data->irq_low, NULL,678 cc2_low_interrupt,679 IRQF_ONESHOT |680 IRQF_TRIGGER_RISING,681 dev_name(dev), data);682 if (ret)683 return ret;684 685 data->rh_alarm.low_alarm_visible = true;686 }687 688 data->irq_high = fwnode_irq_get_byname(dev_fwnode(dev), "high");689 if (data->irq_high > 0) {690 ret = devm_request_threaded_irq(dev, data->irq_high, NULL,691 cc2_high_interrupt,692 IRQF_ONESHOT |693 IRQF_TRIGGER_RISING,694 dev_name(dev), data);695 if (ret)696 return ret;697 698 data->rh_alarm.high_alarm_visible = true;699 }700 701 return ret;702}703 704static const struct hwmon_channel_info *cc2_info[] = {705 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),706 HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN | HWMON_H_MAX |707 HWMON_H_MIN_HYST | HWMON_H_MAX_HYST |708 HWMON_H_MIN_ALARM | HWMON_H_MAX_ALARM),709 NULL710};711 712static const struct hwmon_ops cc2_hwmon_ops = {713 .is_visible = cc2_is_visible,714 .read = cc2_read,715 .write = cc2_write,716};717 718static const struct hwmon_chip_info cc2_chip_info = {719 .ops = &cc2_hwmon_ops,720 .info = cc2_info,721};722 723static int cc2_probe(struct i2c_client *client)724{725 struct cc2_data *data;726 struct device *dev = &client->dev;727 int ret;728 729 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))730 return -EOPNOTSUPP;731 732 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);733 if (!data)734 return -ENOMEM;735 736 i2c_set_clientdata(client, data);737 738 mutex_init(&data->dev_access_lock);739 740 data->client = client;741 742 data->regulator = devm_regulator_get_exclusive(dev, "vdd");743 if (IS_ERR(data->regulator))744 return dev_err_probe(dev, PTR_ERR(data->regulator),745 "Failed to get regulator\n");746 747 ret = cc2_request_ready_irq(data, dev);748 if (ret)749 return dev_err_probe(dev, ret, "Failed to request ready irq\n");750 751 ret = cc2_request_alarm_irqs(data, dev);752 if (ret)753 return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");754 755 data->hwmon = devm_hwmon_device_register_with_info(dev, client->name,756 data, &cc2_chip_info,757 NULL);758 if (IS_ERR(data->hwmon))759 return dev_err_probe(dev, PTR_ERR(data->hwmon),760 "Failed to register hwmon device\n");761 762 return 0;763}764 765static void cc2_remove(struct i2c_client *client)766{767 struct cc2_data *data = i2c_get_clientdata(client);768 769 cc2_disable(data);770}771 772static const struct i2c_device_id cc2_id[] = {773 { "cc2d23" },774 { "cc2d23s" },775 { "cc2d25" },776 { "cc2d25s" },777 { "cc2d33" },778 { "cc2d33s" },779 { "cc2d35" },780 { "cc2d35s" },781 { }782};783MODULE_DEVICE_TABLE(i2c, cc2_id);784 785static const struct of_device_id cc2_of_match[] = {786 { .compatible = "amphenol,cc2d23" },787 { .compatible = "amphenol,cc2d23s" },788 { .compatible = "amphenol,cc2d25" },789 { .compatible = "amphenol,cc2d25s" },790 { .compatible = "amphenol,cc2d33" },791 { .compatible = "amphenol,cc2d33s" },792 { .compatible = "amphenol,cc2d35" },793 { .compatible = "amphenol,cc2d35s" },794 { },795};796MODULE_DEVICE_TABLE(of, cc2_of_match);797 798static struct i2c_driver cc2_driver = {799 .driver = {800 .name = "cc2d23",801 .of_match_table = cc2_of_match,802 },803 .probe = cc2_probe,804 .remove = cc2_remove,805 .id_table = cc2_id,806};807module_i2c_driver(cc2_driver);808 809MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gamil.com>");810MODULE_DESCRIPTION("Amphenol ChipCap 2 humidity and temperature sensor driver");811MODULE_LICENSE("GPL");812