11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lm92 - Hardware monitoring driver 37c81c60f3789a082e141d7a013392af5f78db16aJean Delvare * Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on the lm90 driver, with some ideas taken from the lm_sensors 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lm92 driver as well. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The LM92 is a sensor chip made by National Semiconductor. It reports 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * its own temperature with a 0.0625 deg resolution and a 0.33 deg 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * accuracy. Complete datasheet can be obtained from National's website 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at: 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://www.national.com/pf/LM/LM92.html 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver also supports the MAX6635 sensor chip made by Maxim. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This chip is compatible with the LM92, but has a lesser accuracy 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (1.0 deg). Complete datasheet can be obtained from Maxim's website 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at: 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Since the LM92 was the first chipset supported by this driver, most 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * comments will refer to this chipset, but are actually general and 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * concern all supported chipsets, unless mentioned otherwise. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Support could easily be added for the National Semiconductor LM76 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the LM92. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 43943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h> 446cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare#include <linux/hwmon-sysfs.h> 45943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h> 469a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h> 47dcd8f39230b9f724ba4f55f14ed2bb8119204385Jean Delvare#include <linux/jiffies.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck/* 50a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * The LM92 and MAX6635 have 2 two-state pins for address selection, 51a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * resulting in 4 possible addresses. 52a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck */ 5325e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 5425e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffman I2C_CLIENT_END }; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LM92 registers */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_TEMP 0x00 /* 16-bit, RO */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_TEMP_HYST 0x02 /* 16-bit, RW */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_TEMP_CRIT 0x03 /* 16-bit, RW */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_TEMP_LOW 0x04 /* 16-bit, RW */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_TEMP_HIGH 0x05 /* 16-bit, RW */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LM92_REG_MAN_ID 0x07 /* 16-bit, RO, LM92 only */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck/* 66a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius, 67a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * left-justified in 16-bit registers. No rounding is done, with such 68a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * a resolution it's just not worth it. Note that the MAX6635 doesn't 69a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * make use of the 4 lower bits for limits (i.e. effective resolution 70a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * for limits is 1 degree Celsius). 71a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int TEMP_FROM_REG(s16 reg) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg / 8 * 625 / 10; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 775b963089161b8fb244889c972edf553b9d737545Axel Linstatic inline s16 TEMP_TO_REG(long val) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 795b963089161b8fb244889c972edf553b9d737545Axel Lin val = clamp_val(val, -60000, 160000); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val * 10 / 625 * 8; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Alarm flags are stored in the 3 LSB of the temperature register */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 ALARMS_FROM_REG(s16 reg) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg & 0x0007; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckenum temp_index { 90b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_input, 91b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_crit, 92b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_min, 93b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_max, 94b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_hyst, 95b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_num_regs 96b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck}; 97b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 98b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic const u8 regs[t_num_regs] = { 99b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck [t_input] = LM92_REG_TEMP, 100b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck [t_crit] = LM92_REG_TEMP_CRIT, 101b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck [t_min] = LM92_REG_TEMP_LOW, 102b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck [t_max] = LM92_REG_TEMP_HIGH, 103b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck [t_hyst] = LM92_REG_TEMP_HYST, 104b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck}; 105b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Client data (each client gets its own) */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lm92_data { 108030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct i2c_client *client; 1099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex update_lock; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char valid; /* zero until following fields are valid */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_updated; /* in jiffies */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* registers values */ 114b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck s16 temp[t_num_regs]; /* index with enum temp_index */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sysfs attributes and callback functions 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct lm92_data *lm92_update_device(struct device *dev) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct lm92_data *data = dev_get_drvdata(dev); 124030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct i2c_client *client = data->client; 125b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck int i; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1279a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (time_after(jiffies, data->last_updated + HZ) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || !data->valid) { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Updating lm92 data\n"); 132b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck for (i = 0; i < t_num_regs; i++) { 133b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck data->temp[i] = 134b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck i2c_smbus_read_word_swapped(client, regs[i]); 135b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck } 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_updated = jiffies; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 1; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return data; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 145b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 146b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck char *buf) 147b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck{ 148b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 149b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct lm92_data *data = lm92_update_device(dev); 150b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 151b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 154b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic ssize_t set_temp(struct device *dev, struct device_attribute *devattr, 155b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck const char *buf, size_t count) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 157b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 158030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct lm92_data *data = dev_get_drvdata(dev); 159030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct i2c_client *client = data->client; 160b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck int nr = attr->index; 161b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck long val; 162b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck int err; 163b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 164b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck err = kstrtol(buf, 10, &val); 165b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck if (err) 166b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return err; 167b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 168b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck mutex_lock(&data->update_lock); 169b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck data->temp[nr] = TEMP_TO_REG(val); 170b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck i2c_smbus_write_word_swapped(client, regs[nr], data->temp[nr]); 171b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck mutex_unlock(&data->update_lock); 172b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return count; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 174b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 175b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic ssize_t show_temp_hyst(struct device *dev, 176b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct device_attribute *devattr, char *buf) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 178b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lm92_data *data = lm92_update_device(dev); 180b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]) 181b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck - TEMP_FROM_REG(data->temp[t_hyst])); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 183b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck 184b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic ssize_t show_temp_min_hyst(struct device *dev, 185b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct device_attribute *attr, char *buf) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lm92_data *data = lm92_update_device(dev); 188b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[t_min]) 189b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck + TEMP_FROM_REG(data->temp[t_hyst])); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic ssize_t set_temp_hyst(struct device *dev, 193b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct device_attribute *devattr, 194b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck const char *buf, size_t count) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 196b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 197030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct lm92_data *data = dev_get_drvdata(dev); 198030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct i2c_client *client = data->client; 199a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck long val; 200a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck int err; 201a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck 202a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck err = kstrtol(buf, 10, &val); 203a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck if (err) 204a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck return err; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2065b963089161b8fb244889c972edf553b9d737545Axel Lin val = clamp_val(val, -120000, 220000); 2079a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 2085b963089161b8fb244889c972edf553b9d737545Axel Lin data->temp[t_hyst] = 2095b963089161b8fb244889c972edf553b9d737545Axel Lin TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val); 21090f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST, 2115b963089161b8fb244889c972edf553b9d737545Axel Lin data->temp[t_hyst]); 2129a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeckstatic ssize_t show_alarms(struct device *dev, struct device_attribute *attr, 217a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck char *buf) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lm92_data *data = lm92_update_device(dev); 220b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input])); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2236cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 2246cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare char *buf) 2256cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare{ 2266cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 2276cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare struct lm92_data *data = lm92_update_device(dev); 228b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1); 2296cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare} 2306cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare 231b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); 232b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp, 233b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_crit); 234b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, 235b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck set_temp_hyst, t_crit); 236b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 237b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_min); 238b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp_min_hyst, NULL); 239b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 240b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck t_max); 241b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 2436cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvarestatic SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); 2446cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvarestatic SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); 2456cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvarestatic SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Detection and registration 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lm92_init_client(struct i2c_client *client) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 config; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start the conversions if needed */ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (config & 0x01) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_byte_data(client, LM92_REG_CONFIG, 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config & 0xFE); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 262a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck/* 263a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * The MAX6635 has no identification register, so we have to use tricks 264a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * to identify it reliably. This is somewhat slow. 265a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * Note that we do NOT rely on the 2 MSB of the configuration register 266a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * always reading 0, as suggested by the datasheet, because it was once 267a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * reported not to be true. 268a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max6635_check(struct i2c_client *client) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 temp_low, temp_high, temp_hyst, temp_crit; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 conf; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 275a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck /* 276a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * No manufacturer ID register, so a read from this address will 277a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * always return the last read value. 278a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck */ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 285a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Limits are stored as integer values (signed, 9-bit). */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp_low & 0x7f00) || (temp_high & 0x7f00)) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00)) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 294a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck /* 295a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * Registers addresses were found to cycle over 16-byte boundaries. 296a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * We don't test all registers with all offsets so as to save some 297a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * reads and time, but this should still be sufficient to dismiss 298a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck * non-MAX6635 chips. 299a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck */ 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); 301a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck for (i = 16; i < 96; i *= 2) { 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp_hyst != i2c_smbus_read_word_data(client, 303a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck LM92_REG_TEMP_HYST + i - 16) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || temp_crit != i2c_smbus_read_word_data(client, 305a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck LM92_REG_TEMP_CRIT + i) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || temp_low != i2c_smbus_read_word_data(client, 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LM92_REG_TEMP_LOW + i + 16) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || temp_high != i2c_smbus_read_word_data(client, 309a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck LM92_REG_TEMP_HIGH + i + 32) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || conf != i2c_smbus_read_byte_data(client, 311a318afd890ea4cf1e35543ad100704173edb4406Guenter Roeck LM92_REG_CONFIG + i)) 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 318030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeckstatic struct attribute *lm92_attrs[] = { 319b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_input.dev_attr.attr, 320b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_crit.dev_attr.attr, 321b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 322b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_min.dev_attr.attr, 3230501a3816e5b778830fc2157a6d6bb11a965fc2cMark M. Hoffman &dev_attr_temp1_min_hyst.attr, 324b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_max.dev_attr.attr, 325b8fe58e9532d8cbaa8efcedf95a9c18f726e75ceGuenter Roeck &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 3260501a3816e5b778830fc2157a6d6bb11a965fc2cMark M. Hoffman &dev_attr_alarms.attr, 3276cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 3286cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 3296cb59e915d04f71c62a0ee8fab34de274aa3fe2aJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 3300501a3816e5b778830fc2157a6d6bb11a965fc2cMark M. Hoffman NULL 3310501a3816e5b778830fc2157a6d6bb11a965fc2cMark M. Hoffman}; 332030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter RoeckATTRIBUTE_GROUPS(lm92); 3330501a3816e5b778830fc2157a6d6bb11a965fc2cMark M. Hoffman 334910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */ 335310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int lm92_detect(struct i2c_client *new_client, 336910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare struct i2c_board_info *info) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 338910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare struct i2c_adapter *adapter = new_client->adapter; 33952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare u8 config; 34052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare u16 man_id; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | I2C_FUNC_SMBUS_WORD_DATA)) 344910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare return -ENODEV; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG); 34752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID); 34852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare 34952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare if ((config & 0xe0) == 0x00 && man_id == 0x0180) 35052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare pr_info("lm92: Found National Semiconductor LM92 chip\n"); 35152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare else if (max6635_check(new_client)) 35252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare pr_info("lm92: Found Maxim MAX6635 chip\n"); 35352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare else 35452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare return -ENODEV; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 356910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare strlcpy(info->type, "lm92", I2C_NAME_SIZE); 357910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare 358910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare return 0; 359910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare} 360910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare 361910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvarestatic int lm92_probe(struct i2c_client *new_client, 362910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare const struct i2c_device_id *id) 363910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare{ 364030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck struct device *hwmon_dev; 365910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare struct lm92_data *data; 366910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare 367705375cc41f2bd63dfffcf4830afff76c63e5681Guenter Roeck data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data), 368705375cc41f2bd63dfffcf4830afff76c63e5681Guenter Roeck GFP_KERNEL); 369705375cc41f2bd63dfffcf4830afff76c63e5681Guenter Roeck if (!data) 370705375cc41f2bd63dfffcf4830afff76c63e5681Guenter Roeck return -ENOMEM; 371910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare 372030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck data->client = new_client; 3739a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_init(&data->update_lock); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the chipset */ 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lm92_init_client(new_client); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 378030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev, 379030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck new_client->name, 380030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck data, lm92_groups); 381030004b1edf1d3b7e7a0957b4cb11b28372b8d70Guenter Roeck return PTR_ERR_OR_ZERO(hwmon_dev); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Module and driver stuff 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 389910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvarestatic const struct i2c_device_id lm92_id[] = { 3901f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare { "lm92", 0 }, 391910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare /* max6635 could be added here */ 392910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare { } 393910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare}; 394910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean DelvareMODULE_DEVICE_TABLE(i2c, lm92_id); 395910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver lm92_driver = { 397910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare .class = I2C_CLASS_HWMON, 398cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .driver = { 399cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .name = "lm92", 400cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard }, 401910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare .probe = lm92_probe, 402910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare .id_table = lm92_id, 403910e8dcf16dd7afc08dc1791155cc69e07ca4183Jean Delvare .detect = lm92_detect, 404c3813d6af177fab19e322f3114b1f64fbcf08d71Jean Delvare .address_list = normal_i2c, 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 407f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(lm92_driver); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4097c81c60f3789a082e141d7a013392af5f78db16aJean DelvareMODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("LM92/MAX6635 driver"); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 412