834 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * adm9240.c Part of lm_sensors, Linux kernel modules for hardware4 * monitoring5 *6 * Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>7 * Philip Edelbrock <phil@netroedge.com>8 * Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl>9 * Copyright (C) 2005 Grant Coady <gcoady.lk@gmail.com> with valuable10 * guidance from Jean Delvare11 *12 * Driver supports Analog Devices ADM924013 * Dallas Semiconductor DS178014 * National Semiconductor LM8115 *16 * ADM9240 is the reference, DS1780 and LM81 are register compatibles17 *18 * Voltage Six inputs are scaled by chip, VID also reported19 * Temperature Chip temperature to 0.5'C, maximum and max_hysteris20 * Fans 2 fans, low speed alarm, automatic fan clock divider21 * Alarms 16-bit map of active alarms22 * Analog Out 0..1250 mV output23 *24 * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm'25 *26 * Test hardware: Intel SE440BX-2 desktop motherboard --Grant27 *28 * LM81 extended temp reading not implemented29 */30 31#include <linux/bits.h>32#include <linux/init.h>33#include <linux/module.h>34#include <linux/slab.h>35#include <linux/i2c.h>36#include <linux/hwmon-sysfs.h>37#include <linux/hwmon.h>38#include <linux/hwmon-vid.h>39#include <linux/err.h>40#include <linux/mutex.h>41#include <linux/regmap.h>42 43/* Addresses to scan */44static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,45 I2C_CLIENT_END };46 47enum chips { adm9240, ds1780, lm81 };48 49/* ADM9240 registers */50#define ADM9240_REG_MAN_ID 0x3e51#define ADM9240_REG_DIE_REV 0x3f52#define ADM9240_REG_CONFIG 0x4053 54#define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */55#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)56#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)57#define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */58#define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr))59#define ADM9240_REG_INT(nr) (0x41 + (nr))60#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))61#define ADM9240_REG_TEMP 0x2762#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */63#define ADM9240_REG_ANALOG_OUT 0x1964#define ADM9240_REG_CHASSIS_CLEAR 0x4665#define ADM9240_REG_VID_FAN_DIV 0x4766#define ADM9240_REG_I2C_ADDR 0x4867#define ADM9240_REG_VID4 0x4968#define ADM9240_REG_TEMP_CONF 0x4b69 70/* generalised scaling with integer rounding */71static inline int SCALE(long val, int mul, int div)72{73 if (val < 0)74 return (val * mul - div / 2) / div;75 else76 return (val * mul + div / 2) / div;77}78 79/* adm9240 internally scales voltage measurements */80static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };81 82static inline unsigned int IN_FROM_REG(u8 reg, int n)83{84 return SCALE(reg, nom_mv[n], 192);85}86 87static inline u8 IN_TO_REG(unsigned long val, int n)88{89 val = clamp_val(val, 0, nom_mv[n] * 255 / 192);90 return SCALE(val, 192, nom_mv[n]);91}92 93/* temperature range: -40..125, 127 disables temperature alarm */94static inline s8 TEMP_TO_REG(long val)95{96 val = clamp_val(val, -40000, 127000);97 return SCALE(val, 1, 1000);98}99 100/* two fans, each with low fan speed limit */101static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)102{103 if (!reg) /* error */104 return -1;105 106 if (reg == 255)107 return 0;108 109 return SCALE(1350000, 1, reg * div);110}111 112/* analog out 0..1250mV */113static inline u8 AOUT_TO_REG(unsigned long val)114{115 val = clamp_val(val, 0, 1250);116 return SCALE(val, 255, 1250);117}118 119static inline unsigned int AOUT_FROM_REG(u8 reg)120{121 return SCALE(reg, 1250, 255);122}123 124/* per client data */125struct adm9240_data {126 struct device *dev;127 struct regmap *regmap;128 struct mutex update_lock;129 130 u8 fan_div[2]; /* rw fan1_div, read-only accessor */131 u8 vrm; /* -- vrm set on startup, no accessor */132};133 134/* write new fan div, callers must hold data->update_lock */135static int adm9240_write_fan_div(struct adm9240_data *data, int channel, u8 fan_div)136{137 unsigned int reg, old, shift = (channel + 2) * 2;138 int err;139 140 err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®);141 if (err < 0)142 return err;143 old = (reg >> shift) & 3;144 reg &= ~(3 << shift);145 reg |= (fan_div << shift);146 err = regmap_write(data->regmap, ADM9240_REG_VID_FAN_DIV, reg);147 if (err < 0)148 return err;149 dev_dbg(data->dev,150 "fan%d clock divider changed from %lu to %lu\n",151 channel + 1, BIT(old), BIT(fan_div));152 153 return 0;154}155 156/*157 * set fan speed low limit:158 *159 * - value is zero: disable fan speed low limit alarm160 *161 * - value is below fan speed measurement range: enable fan speed low162 * limit alarm to be asserted while fan speed too slow to measure163 *164 * - otherwise: select fan clock divider to suit fan speed low limit,165 * measurement code may adjust registers to ensure fan speed reading166 */167static int adm9240_fan_min_write(struct adm9240_data *data, int channel, long val)168{169 u8 new_div;170 u8 fan_min;171 int err;172 173 mutex_lock(&data->update_lock);174 175 if (!val) {176 fan_min = 255;177 new_div = data->fan_div[channel];178 179 dev_dbg(data->dev, "fan%u low limit set disabled\n", channel + 1);180 } else if (val < 1350000 / (8 * 254)) {181 new_div = 3;182 fan_min = 254;183 184 dev_dbg(data->dev, "fan%u low limit set minimum %u\n",185 channel + 1, FAN_FROM_REG(254, BIT(new_div)));186 } else {187 unsigned int new_min = 1350000 / val;188 189 new_div = 0;190 while (new_min > 192 && new_div < 3) {191 new_div++;192 new_min /= 2;193 }194 if (!new_min) /* keep > 0 */195 new_min++;196 197 fan_min = new_min;198 199 dev_dbg(data->dev, "fan%u low limit set fan speed %u\n",200 channel + 1, FAN_FROM_REG(new_min, BIT(new_div)));201 }202 203 if (new_div != data->fan_div[channel]) {204 data->fan_div[channel] = new_div;205 adm9240_write_fan_div(data, channel, new_div);206 }207 err = regmap_write(data->regmap, ADM9240_REG_FAN_MIN(channel), fan_min);208 209 mutex_unlock(&data->update_lock);210 211 return err;212}213 214static ssize_t cpu0_vid_show(struct device *dev,215 struct device_attribute *attr, char *buf)216{217 struct adm9240_data *data = dev_get_drvdata(dev);218 unsigned int regval;219 int err;220 u8 vid;221 222 err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®val);223 if (err < 0)224 return err;225 vid = regval & 0x0f;226 err = regmap_read(data->regmap, ADM9240_REG_VID4, ®val);227 if (err < 0)228 return err;229 vid |= (regval & 1) << 4;230 return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));231}232static DEVICE_ATTR_RO(cpu0_vid);233 234static ssize_t aout_output_show(struct device *dev,235 struct device_attribute *attr, char *buf)236{237 struct adm9240_data *data = dev_get_drvdata(dev);238 unsigned int regval;239 int err;240 241 err = regmap_read(data->regmap, ADM9240_REG_ANALOG_OUT, ®val);242 if (err)243 return err;244 245 return sprintf(buf, "%d\n", AOUT_FROM_REG(regval));246}247 248static ssize_t aout_output_store(struct device *dev,249 struct device_attribute *attr,250 const char *buf, size_t count)251{252 struct adm9240_data *data = dev_get_drvdata(dev);253 long val;254 int err;255 256 err = kstrtol(buf, 10, &val);257 if (err)258 return err;259 260 err = regmap_write(data->regmap, ADM9240_REG_ANALOG_OUT, AOUT_TO_REG(val));261 return err < 0 ? err : count;262}263static DEVICE_ATTR_RW(aout_output);264 265static struct attribute *adm9240_attrs[] = {266 &dev_attr_aout_output.attr,267 &dev_attr_cpu0_vid.attr,268 NULL269};270 271ATTRIBUTE_GROUPS(adm9240);272 273/*** sensor chip detect and driver install ***/274 275/* Return 0 if detection is successful, -ENODEV otherwise */276static int adm9240_detect(struct i2c_client *new_client,277 struct i2c_board_info *info)278{279 struct i2c_adapter *adapter = new_client->adapter;280 const char *name = "";281 int address = new_client->addr;282 u8 man_id, die_rev;283 284 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))285 return -ENODEV;286 287 /* verify chip: reg address should match i2c address */288 if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR) != address)289 return -ENODEV;290 291 /* check known chip manufacturer */292 man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID);293 if (man_id == 0x23)294 name = "adm9240";295 else if (man_id == 0xda)296 name = "ds1780";297 else if (man_id == 0x01)298 name = "lm81";299 else300 return -ENODEV;301 302 /* successful detect, print chip info */303 die_rev = i2c_smbus_read_byte_data(new_client, ADM9240_REG_DIE_REV);304 dev_info(&adapter->dev, "found %s revision %u\n",305 man_id == 0x23 ? "ADM9240" :306 man_id == 0xda ? "DS1780" : "LM81", die_rev);307 308 strscpy(info->type, name, I2C_NAME_SIZE);309 310 return 0;311}312 313static int adm9240_init_client(struct adm9240_data *data)314{315 unsigned int regval;316 u8 conf, mode;317 int err;318 319 err = regmap_raw_read(data->regmap, ADM9240_REG_CONFIG, &conf, 1);320 if (err < 0)321 return err;322 err = regmap_raw_read(data->regmap, ADM9240_REG_TEMP_CONF, &mode, 1);323 if (err < 0)324 return err;325 mode &= 3;326 327 data->vrm = vid_which_vrm(); /* need this to report vid as mV */328 329 dev_info(data->dev, "Using VRM: %d.%d\n", data->vrm / 10,330 data->vrm % 10);331 332 if (conf & 1) { /* measurement cycle running: report state */333 334 dev_info(data->dev, "status: config 0x%02x mode %u\n",335 conf, mode);336 337 } else { /* cold start: open limits before starting chip */338 int i;339 340 for (i = 0; i < 6; i++) {341 err = regmap_write(data->regmap,342 ADM9240_REG_IN_MIN(i), 0);343 if (err < 0)344 return err;345 err = regmap_write(data->regmap,346 ADM9240_REG_IN_MAX(i), 255);347 if (err < 0)348 return err;349 }350 for (i = 0; i < 2; i++) {351 err = regmap_write(data->regmap,352 ADM9240_REG_FAN_MIN(i), 255);353 if (err < 0)354 return err;355 }356 for (i = 0; i < 2; i++) {357 err = regmap_write(data->regmap,358 ADM9240_REG_TEMP_MAX(i), 127);359 if (err < 0)360 return err;361 }362 363 /* start measurement cycle */364 err = regmap_write(data->regmap, ADM9240_REG_CONFIG, 1);365 if (err < 0)366 return err;367 368 dev_info(data->dev,369 "cold start: config was 0x%02x mode %u\n", conf, mode);370 }371 372 /* read fan divs */373 err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®val);374 if (err < 0)375 return err;376 data->fan_div[0] = (regval >> 4) & 3;377 data->fan_div[1] = (regval >> 6) & 3;378 return 0;379}380 381static int adm9240_chip_read(struct device *dev, u32 attr, long *val)382{383 struct adm9240_data *data = dev_get_drvdata(dev);384 u8 regs[2];385 int err;386 387 switch (attr) {388 case hwmon_chip_alarms:389 err = regmap_bulk_read(data->regmap, ADM9240_REG_INT(0), ®s, 2);390 if (err < 0)391 return err;392 *val = regs[0] | regs[1] << 8;393 break;394 default:395 return -EOPNOTSUPP;396 }397 return 0;398}399 400static int adm9240_intrusion_read(struct device *dev, u32 attr, long *val)401{402 struct adm9240_data *data = dev_get_drvdata(dev);403 unsigned int regval;404 int err;405 406 switch (attr) {407 case hwmon_intrusion_alarm:408 err = regmap_read(data->regmap, ADM9240_REG_INT(1), ®val);409 if (err < 0)410 return err;411 *val = !!(regval & BIT(4));412 break;413 default:414 return -EOPNOTSUPP;415 }416 return 0;417}418 419static int adm9240_intrusion_write(struct device *dev, u32 attr, long val)420{421 struct adm9240_data *data = dev_get_drvdata(dev);422 int err;423 424 switch (attr) {425 case hwmon_intrusion_alarm:426 if (val)427 return -EINVAL;428 err = regmap_write(data->regmap, ADM9240_REG_CHASSIS_CLEAR, 0x80);429 if (err < 0)430 return err;431 dev_dbg(data->dev, "chassis intrusion latch cleared\n");432 break;433 default:434 return -EOPNOTSUPP;435 }436 return 0;437}438 439static int adm9240_in_read(struct device *dev, u32 attr, int channel, long *val)440{441 struct adm9240_data *data = dev_get_drvdata(dev);442 unsigned int regval;443 int reg;444 int err;445 446 switch (attr) {447 case hwmon_in_input:448 reg = ADM9240_REG_IN(channel);449 break;450 case hwmon_in_min:451 reg = ADM9240_REG_IN_MIN(channel);452 break;453 case hwmon_in_max:454 reg = ADM9240_REG_IN_MAX(channel);455 break;456 case hwmon_in_alarm:457 if (channel < 4) {458 reg = ADM9240_REG_INT(0);459 } else {460 reg = ADM9240_REG_INT(1);461 channel -= 4;462 }463 err = regmap_read(data->regmap, reg, ®val);464 if (err < 0)465 return err;466 *val = !!(regval & BIT(channel));467 return 0;468 default:469 return -EOPNOTSUPP;470 }471 err = regmap_read(data->regmap, reg, ®val);472 if (err < 0)473 return err;474 *val = IN_FROM_REG(regval, channel);475 return 0;476}477 478static int adm9240_in_write(struct device *dev, u32 attr, int channel, long val)479{480 struct adm9240_data *data = dev_get_drvdata(dev);481 int reg;482 483 switch (attr) {484 case hwmon_in_min:485 reg = ADM9240_REG_IN_MIN(channel);486 break;487 case hwmon_in_max:488 reg = ADM9240_REG_IN_MAX(channel);489 break;490 default:491 return -EOPNOTSUPP;492 }493 return regmap_write(data->regmap, reg, IN_TO_REG(val, channel));494}495 496static int adm9240_fan_read(struct device *dev, u32 attr, int channel, long *val)497{498 struct adm9240_data *data = dev_get_drvdata(dev);499 unsigned int regval;500 int err;501 502 switch (attr) {503 case hwmon_fan_input:504 mutex_lock(&data->update_lock);505 err = regmap_read(data->regmap, ADM9240_REG_FAN(channel), ®val);506 if (err < 0) {507 mutex_unlock(&data->update_lock);508 return err;509 }510 if (regval == 255 && data->fan_div[channel] < 3) {511 /* adjust fan clock divider on overflow */512 err = adm9240_write_fan_div(data, channel,513 ++data->fan_div[channel]);514 if (err) {515 mutex_unlock(&data->update_lock);516 return err;517 }518 }519 *val = FAN_FROM_REG(regval, BIT(data->fan_div[channel]));520 mutex_unlock(&data->update_lock);521 break;522 case hwmon_fan_div:523 *val = BIT(data->fan_div[channel]);524 break;525 case hwmon_fan_min:526 err = regmap_read(data->regmap, ADM9240_REG_FAN_MIN(channel), ®val);527 if (err < 0)528 return err;529 *val = FAN_FROM_REG(regval, BIT(data->fan_div[channel]));530 break;531 case hwmon_fan_alarm:532 err = regmap_read(data->regmap, ADM9240_REG_INT(0), ®val);533 if (err < 0)534 return err;535 *val = !!(regval & BIT(channel + 6));536 break;537 default:538 return -EOPNOTSUPP;539 }540 return 0;541}542 543static int adm9240_fan_write(struct device *dev, u32 attr, int channel, long val)544{545 struct adm9240_data *data = dev_get_drvdata(dev);546 int err;547 548 switch (attr) {549 case hwmon_fan_min:550 err = adm9240_fan_min_write(data, channel, val);551 if (err < 0)552 return err;553 break;554 default:555 return -EOPNOTSUPP;556 }557 return 0;558}559 560static int adm9240_temp_read(struct device *dev, u32 attr, int channel, long *val)561{562 struct adm9240_data *data = dev_get_drvdata(dev);563 unsigned int regval;564 int err, temp;565 566 switch (attr) {567 case hwmon_temp_input:568 err = regmap_read(data->regmap, ADM9240_REG_TEMP, ®val);569 if (err < 0)570 return err;571 temp = regval << 1;572 err = regmap_read(data->regmap, ADM9240_REG_TEMP_CONF, ®val);573 if (err < 0)574 return err;575 temp |= regval >> 7;576 *val = sign_extend32(temp, 8) * 500;577 break;578 case hwmon_temp_max:579 err = regmap_read(data->regmap, ADM9240_REG_TEMP_MAX(0), ®val);580 if (err < 0)581 return err;582 *val = (s8)regval * 1000;583 break;584 case hwmon_temp_max_hyst:585 err = regmap_read(data->regmap, ADM9240_REG_TEMP_MAX(1), ®val);586 if (err < 0)587 return err;588 *val = (s8)regval * 1000;589 break;590 case hwmon_temp_alarm:591 err = regmap_read(data->regmap, ADM9240_REG_INT(0), ®val);592 if (err < 0)593 return err;594 *val = !!(regval & BIT(4));595 break;596 default:597 return -EOPNOTSUPP;598 }599 return 0;600}601 602static int adm9240_temp_write(struct device *dev, u32 attr, int channel, long val)603{604 struct adm9240_data *data = dev_get_drvdata(dev);605 int reg;606 607 switch (attr) {608 case hwmon_temp_max:609 reg = ADM9240_REG_TEMP_MAX(0);610 break;611 case hwmon_temp_max_hyst:612 reg = ADM9240_REG_TEMP_MAX(1);613 break;614 default:615 return -EOPNOTSUPP;616 }617 return regmap_write(data->regmap, reg, TEMP_TO_REG(val));618}619 620static int adm9240_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,621 int channel, long *val)622{623 switch (type) {624 case hwmon_chip:625 return adm9240_chip_read(dev, attr, val);626 case hwmon_intrusion:627 return adm9240_intrusion_read(dev, attr, val);628 case hwmon_in:629 return adm9240_in_read(dev, attr, channel, val);630 case hwmon_fan:631 return adm9240_fan_read(dev, attr, channel, val);632 case hwmon_temp:633 return adm9240_temp_read(dev, attr, channel, val);634 default:635 return -EOPNOTSUPP;636 }637}638 639static int adm9240_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,640 int channel, long val)641{642 switch (type) {643 case hwmon_intrusion:644 return adm9240_intrusion_write(dev, attr, val);645 case hwmon_in:646 return adm9240_in_write(dev, attr, channel, val);647 case hwmon_fan:648 return adm9240_fan_write(dev, attr, channel, val);649 case hwmon_temp:650 return adm9240_temp_write(dev, attr, channel, val);651 default:652 return -EOPNOTSUPP;653 }654}655 656static umode_t adm9240_is_visible(const void *_data, enum hwmon_sensor_types type,657 u32 attr, int channel)658{659 umode_t mode = 0;660 661 switch (type) {662 case hwmon_chip:663 switch (attr) {664 case hwmon_chip_alarms:665 mode = 0444;666 break;667 default:668 break;669 }670 break;671 case hwmon_intrusion:672 switch (attr) {673 case hwmon_intrusion_alarm:674 mode = 0644;675 break;676 default:677 break;678 }679 break;680 case hwmon_temp:681 switch (attr) {682 case hwmon_temp:683 case hwmon_temp_alarm:684 mode = 0444;685 break;686 case hwmon_temp_max:687 case hwmon_temp_max_hyst:688 mode = 0644;689 break;690 default:691 break;692 }693 break;694 case hwmon_fan:695 switch (attr) {696 case hwmon_fan_input:697 case hwmon_fan_div:698 case hwmon_fan_alarm:699 mode = 0444;700 break;701 case hwmon_fan_min:702 mode = 0644;703 break;704 default:705 break;706 }707 break;708 case hwmon_in:709 switch (attr) {710 case hwmon_in_input:711 case hwmon_in_alarm:712 mode = 0444;713 break;714 case hwmon_in_min:715 case hwmon_in_max:716 mode = 0644;717 break;718 default:719 break;720 }721 break;722 default:723 break;724 }725 return mode;726}727 728static const struct hwmon_ops adm9240_hwmon_ops = {729 .is_visible = adm9240_is_visible,730 .read = adm9240_read,731 .write = adm9240_write,732};733 734static const struct hwmon_channel_info * const adm9240_info[] = {735 HWMON_CHANNEL_INFO(chip, HWMON_C_ALARMS),736 HWMON_CHANNEL_INFO(intrusion, HWMON_INTRUSION_ALARM),737 HWMON_CHANNEL_INFO(temp,738 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_ALARM),739 HWMON_CHANNEL_INFO(in,740 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM,741 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM,742 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM,743 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM,744 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM,745 HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_ALARM),746 HWMON_CHANNEL_INFO(fan,747 HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_DIV | HWMON_F_ALARM,748 HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_DIV | HWMON_F_ALARM),749 NULL750};751 752static const struct hwmon_chip_info adm9240_chip_info = {753 .ops = &adm9240_hwmon_ops,754 .info = adm9240_info,755};756 757static bool adm9240_volatile_reg(struct device *dev, unsigned int reg)758{759 switch (reg) {760 case ADM9240_REG_IN(0) ... ADM9240_REG_IN(5):761 case ADM9240_REG_FAN(0) ... ADM9240_REG_FAN(1):762 case ADM9240_REG_INT(0) ... ADM9240_REG_INT(1):763 case ADM9240_REG_TEMP:764 case ADM9240_REG_TEMP_CONF:765 case ADM9240_REG_VID_FAN_DIV:766 case ADM9240_REG_VID4:767 case ADM9240_REG_ANALOG_OUT:768 return true;769 default:770 return false;771 }772}773 774static const struct regmap_config adm9240_regmap_config = {775 .reg_bits = 8,776 .val_bits = 8,777 .use_single_read = true,778 .use_single_write = true,779 .volatile_reg = adm9240_volatile_reg,780};781 782static int adm9240_probe(struct i2c_client *client)783{784 struct device *dev = &client->dev;785 struct device *hwmon_dev;786 struct adm9240_data *data;787 int err;788 789 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);790 if (!data)791 return -ENOMEM;792 793 data->dev = dev;794 mutex_init(&data->update_lock);795 data->regmap = devm_regmap_init_i2c(client, &adm9240_regmap_config);796 if (IS_ERR(data->regmap))797 return PTR_ERR(data->regmap);798 799 err = adm9240_init_client(data);800 if (err < 0)801 return err;802 803 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,804 &adm9240_chip_info,805 adm9240_groups);806 return PTR_ERR_OR_ZERO(hwmon_dev);807}808 809static const struct i2c_device_id adm9240_id[] = {810 { "adm9240", adm9240 },811 { "ds1780", ds1780 },812 { "lm81", lm81 },813 { }814};815MODULE_DEVICE_TABLE(i2c, adm9240_id);816 817static struct i2c_driver adm9240_driver = {818 .class = I2C_CLASS_HWMON,819 .driver = {820 .name = "adm9240",821 },822 .probe = adm9240_probe,823 .id_table = adm9240_id,824 .detect = adm9240_detect,825 .address_list = normal_i2c,826};827 828module_i2c_driver(adm9240_driver);829 830MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "831 "Grant Coady <gcoady.lk@gmail.com> and others");832MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");833MODULE_LICENSE("GPL");834