18d5d45fbSJean Delvare /* 28d5d45fbSJean Delvare * lm83.c - Part of lm_sensors, Linux kernel modules for hardware 38d5d45fbSJean Delvare * monitoring 4b57dc394SJean Delvare * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org> 58d5d45fbSJean Delvare * 68d5d45fbSJean Delvare * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is 78d5d45fbSJean Delvare * a sensor chip made by National Semiconductor. It reports up to four 88d5d45fbSJean Delvare * temperatures (its own plus up to three external ones) with a 1 deg 98d5d45fbSJean Delvare * resolution and a 3-4 deg accuracy. Complete datasheet can be obtained 108d5d45fbSJean Delvare * from National's website at: 118d5d45fbSJean Delvare * http://www.national.com/pf/LM/LM83.html 128d5d45fbSJean Delvare * Since the datasheet omits to give the chip stepping code, I give it 138d5d45fbSJean Delvare * here: 0x03 (at register 0xff). 148d5d45fbSJean Delvare * 1543cb7ebeSJordan Crouse * Also supports the LM82 temp sensor, which is basically a stripped down 1643cb7ebeSJordan Crouse * model of the LM83. Datasheet is here: 1743cb7ebeSJordan Crouse * http://www.national.com/pf/LM/LM82.html 1843cb7ebeSJordan Crouse * 198d5d45fbSJean Delvare * This program is free software; you can redistribute it and/or modify 208d5d45fbSJean Delvare * it under the terms of the GNU General Public License as published by 218d5d45fbSJean Delvare * the Free Software Foundation; either version 2 of the License, or 228d5d45fbSJean Delvare * (at your option) any later version. 238d5d45fbSJean Delvare * 248d5d45fbSJean Delvare * This program is distributed in the hope that it will be useful, 258d5d45fbSJean Delvare * but WITHOUT ANY WARRANTY; without even the implied warranty of 268d5d45fbSJean Delvare * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 278d5d45fbSJean Delvare * GNU General Public License for more details. 288d5d45fbSJean Delvare * 298d5d45fbSJean Delvare * You should have received a copy of the GNU General Public License 308d5d45fbSJean Delvare * along with this program; if not, write to the Free Software 318d5d45fbSJean Delvare * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 328d5d45fbSJean Delvare */ 338d5d45fbSJean Delvare 348d5d45fbSJean Delvare #include <linux/module.h> 358d5d45fbSJean Delvare #include <linux/init.h> 368d5d45fbSJean Delvare #include <linux/slab.h> 378d5d45fbSJean Delvare #include <linux/jiffies.h> 388d5d45fbSJean Delvare #include <linux/i2c.h> 398d5d45fbSJean Delvare #include <linux/hwmon-sysfs.h> 40943b0830SMark M. Hoffman #include <linux/hwmon.h> 41943b0830SMark M. Hoffman #include <linux/err.h> 429a61bf63SIngo Molnar #include <linux/mutex.h> 430e39e01cSJean Delvare #include <linux/sysfs.h> 448d5d45fbSJean Delvare 458d5d45fbSJean Delvare /* 468d5d45fbSJean Delvare * Addresses to scan 478d5d45fbSJean Delvare * Address is selected using 2 three-level pins, resulting in 9 possible 488d5d45fbSJean Delvare * addresses. 498d5d45fbSJean Delvare */ 508d5d45fbSJean Delvare 5125e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 5225e9c86dSMark M. Hoffman 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; 538d5d45fbSJean Delvare 548d5d45fbSJean Delvare /* 558d5d45fbSJean Delvare * Insmod parameters 568d5d45fbSJean Delvare */ 578d5d45fbSJean Delvare 5843cb7ebeSJordan Crouse I2C_CLIENT_INSMOD_2(lm83, lm82); 598d5d45fbSJean Delvare 608d5d45fbSJean Delvare /* 618d5d45fbSJean Delvare * The LM83 registers 628d5d45fbSJean Delvare * Manufacturer ID is 0x01 for National Semiconductor. 638d5d45fbSJean Delvare */ 648d5d45fbSJean Delvare 658d5d45fbSJean Delvare #define LM83_REG_R_MAN_ID 0xFE 668d5d45fbSJean Delvare #define LM83_REG_R_CHIP_ID 0xFF 678d5d45fbSJean Delvare #define LM83_REG_R_CONFIG 0x03 688d5d45fbSJean Delvare #define LM83_REG_W_CONFIG 0x09 698d5d45fbSJean Delvare #define LM83_REG_R_STATUS1 0x02 708d5d45fbSJean Delvare #define LM83_REG_R_STATUS2 0x35 718d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_TEMP 0x00 728d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_HIGH 0x05 738d5d45fbSJean Delvare #define LM83_REG_W_LOCAL_HIGH 0x0B 748d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_TEMP 0x30 758d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_HIGH 0x38 768d5d45fbSJean Delvare #define LM83_REG_W_REMOTE1_HIGH 0x50 778d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_TEMP 0x01 788d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_HIGH 0x07 798d5d45fbSJean Delvare #define LM83_REG_W_REMOTE2_HIGH 0x0D 808d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_TEMP 0x31 818d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_HIGH 0x3A 828d5d45fbSJean Delvare #define LM83_REG_W_REMOTE3_HIGH 0x52 838d5d45fbSJean Delvare #define LM83_REG_R_TCRIT 0x42 848d5d45fbSJean Delvare #define LM83_REG_W_TCRIT 0x5A 858d5d45fbSJean Delvare 868d5d45fbSJean Delvare /* 878d5d45fbSJean Delvare * Conversions and various macros 888d5d45fbSJean Delvare * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius. 898d5d45fbSJean Delvare */ 908d5d45fbSJean Delvare 918d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 928d5d45fbSJean Delvare #define TEMP_TO_REG(val) ((val) <= -128000 ? -128 : \ 938d5d45fbSJean Delvare (val) >= 127000 ? 127 : \ 948d5d45fbSJean Delvare (val) < 0 ? ((val) - 500) / 1000 : \ 958d5d45fbSJean Delvare ((val) + 500) / 1000) 968d5d45fbSJean Delvare 978d5d45fbSJean Delvare static const u8 LM83_REG_R_TEMP[] = { 988d5d45fbSJean Delvare LM83_REG_R_LOCAL_TEMP, 998d5d45fbSJean Delvare LM83_REG_R_REMOTE1_TEMP, 1008d5d45fbSJean Delvare LM83_REG_R_REMOTE2_TEMP, 1018d5d45fbSJean Delvare LM83_REG_R_REMOTE3_TEMP, 1028d5d45fbSJean Delvare LM83_REG_R_LOCAL_HIGH, 1038d5d45fbSJean Delvare LM83_REG_R_REMOTE1_HIGH, 1048d5d45fbSJean Delvare LM83_REG_R_REMOTE2_HIGH, 1058d5d45fbSJean Delvare LM83_REG_R_REMOTE3_HIGH, 1068d5d45fbSJean Delvare LM83_REG_R_TCRIT, 1078d5d45fbSJean Delvare }; 1088d5d45fbSJean Delvare 1098d5d45fbSJean Delvare static const u8 LM83_REG_W_HIGH[] = { 1108d5d45fbSJean Delvare LM83_REG_W_LOCAL_HIGH, 1118d5d45fbSJean Delvare LM83_REG_W_REMOTE1_HIGH, 1128d5d45fbSJean Delvare LM83_REG_W_REMOTE2_HIGH, 1138d5d45fbSJean Delvare LM83_REG_W_REMOTE3_HIGH, 1148d5d45fbSJean Delvare LM83_REG_W_TCRIT, 1158d5d45fbSJean Delvare }; 1168d5d45fbSJean Delvare 1178d5d45fbSJean Delvare /* 1188d5d45fbSJean Delvare * Functions declaration 1198d5d45fbSJean Delvare */ 1208d5d45fbSJean Delvare 121310ec792SJean Delvare static int lm83_detect(struct i2c_client *new_client, 122b6aacdceSJean Delvare struct i2c_board_info *info); 123b6aacdceSJean Delvare static int lm83_probe(struct i2c_client *client, 124b6aacdceSJean Delvare const struct i2c_device_id *id); 125b6aacdceSJean Delvare static int lm83_remove(struct i2c_client *client); 1268d5d45fbSJean Delvare static struct lm83_data *lm83_update_device(struct device *dev); 1278d5d45fbSJean Delvare 1288d5d45fbSJean Delvare /* 1298d5d45fbSJean Delvare * Driver data (common to all clients) 1308d5d45fbSJean Delvare */ 1318d5d45fbSJean Delvare 132b6aacdceSJean Delvare static const struct i2c_device_id lm83_id[] = { 133b6aacdceSJean Delvare { "lm83", lm83 }, 134b6aacdceSJean Delvare { "lm82", lm82 }, 135b6aacdceSJean Delvare { } 136b6aacdceSJean Delvare }; 137b6aacdceSJean Delvare MODULE_DEVICE_TABLE(i2c, lm83_id); 138b6aacdceSJean Delvare 1398d5d45fbSJean Delvare static struct i2c_driver lm83_driver = { 140b6aacdceSJean Delvare .class = I2C_CLASS_HWMON, 141cdaf7934SLaurent Riffard .driver = { 1428d5d45fbSJean Delvare .name = "lm83", 143cdaf7934SLaurent Riffard }, 144b6aacdceSJean Delvare .probe = lm83_probe, 145b6aacdceSJean Delvare .remove = lm83_remove, 146b6aacdceSJean Delvare .id_table = lm83_id, 147b6aacdceSJean Delvare .detect = lm83_detect, 148c3813d6aSJean Delvare .address_list = normal_i2c, 1498d5d45fbSJean Delvare }; 1508d5d45fbSJean Delvare 1518d5d45fbSJean Delvare /* 1528d5d45fbSJean Delvare * Client data (each client gets its own) 1538d5d45fbSJean Delvare */ 1548d5d45fbSJean Delvare 1558d5d45fbSJean Delvare struct lm83_data { 1561beeffe4STony Jones struct device *hwmon_dev; 1579a61bf63SIngo Molnar struct mutex update_lock; 1588d5d45fbSJean Delvare char valid; /* zero until following fields are valid */ 1598d5d45fbSJean Delvare unsigned long last_updated; /* in jiffies */ 1608d5d45fbSJean Delvare 1618d5d45fbSJean Delvare /* registers values */ 1628d5d45fbSJean Delvare s8 temp[9]; /* 0..3: input 1-4, 1638d5d45fbSJean Delvare 4..7: high limit 1-4, 1648d5d45fbSJean Delvare 8 : critical limit */ 1658d5d45fbSJean Delvare u16 alarms; /* bitvector, combined */ 1668d5d45fbSJean Delvare }; 1678d5d45fbSJean Delvare 1688d5d45fbSJean Delvare /* 1698d5d45fbSJean Delvare * Sysfs stuff 1708d5d45fbSJean Delvare */ 1718d5d45fbSJean Delvare 1728d5d45fbSJean Delvare static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 1738d5d45fbSJean Delvare char *buf) 1748d5d45fbSJean Delvare { 1758d5d45fbSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1768d5d45fbSJean Delvare struct lm83_data *data = lm83_update_device(dev); 1778d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); 1788d5d45fbSJean Delvare } 1798d5d45fbSJean Delvare 1808d5d45fbSJean Delvare static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, 1818d5d45fbSJean Delvare const char *buf, size_t count) 1828d5d45fbSJean Delvare { 1838d5d45fbSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1848d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 1858d5d45fbSJean Delvare struct lm83_data *data = i2c_get_clientdata(client); 1868d5d45fbSJean Delvare long val = simple_strtol(buf, NULL, 10); 1878d5d45fbSJean Delvare int nr = attr->index; 1888d5d45fbSJean Delvare 1899a61bf63SIngo Molnar mutex_lock(&data->update_lock); 1908d5d45fbSJean Delvare data->temp[nr] = TEMP_TO_REG(val); 1918d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], 1928d5d45fbSJean Delvare data->temp[nr]); 1939a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 1948d5d45fbSJean Delvare return count; 1958d5d45fbSJean Delvare } 1968d5d45fbSJean Delvare 1978d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, 1988d5d45fbSJean Delvare char *buf) 1998d5d45fbSJean Delvare { 2008d5d45fbSJean Delvare struct lm83_data *data = lm83_update_device(dev); 2018d5d45fbSJean Delvare return sprintf(buf, "%d\n", data->alarms); 2028d5d45fbSJean Delvare } 2038d5d45fbSJean Delvare 2042d45771eSJean Delvare static ssize_t show_alarm(struct device *dev, struct device_attribute 2052d45771eSJean Delvare *devattr, char *buf) 2062d45771eSJean Delvare { 2072d45771eSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 2082d45771eSJean Delvare struct lm83_data *data = lm83_update_device(dev); 2092d45771eSJean Delvare int bitnr = attr->index; 2102d45771eSJean Delvare 2112d45771eSJean Delvare return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); 2122d45771eSJean Delvare } 2132d45771eSJean Delvare 2148d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 2158d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); 2168d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); 2178d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); 2188d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, 2198d5d45fbSJean Delvare set_temp, 4); 2208d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, 2218d5d45fbSJean Delvare set_temp, 5); 2228d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp, 2238d5d45fbSJean Delvare set_temp, 6); 2248d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp, 2258d5d45fbSJean Delvare set_temp, 7); 2268d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8); 2278d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8); 2288d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, 2298d5d45fbSJean Delvare set_temp, 8); 2308d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); 2312d45771eSJean Delvare 2322d45771eSJean Delvare /* Individual alarm files */ 2332d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); 2342d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); 2357817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); 2362d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); 2372d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); 2382d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); 2392d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); 2407817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10); 2412d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); 2427817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13); 2432d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); 2442d45771eSJean Delvare /* Raw alarm file for compatibility */ 2458d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 2468d5d45fbSJean Delvare 2470e39e01cSJean Delvare static struct attribute *lm83_attributes[] = { 2480e39e01cSJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 2490e39e01cSJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 2500e39e01cSJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 2510e39e01cSJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 2520e39e01cSJean Delvare &sensor_dev_attr_temp1_crit.dev_attr.attr, 2530e39e01cSJean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 2540e39e01cSJean Delvare 2550e39e01cSJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 2560e39e01cSJean Delvare &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 2577817a39eSJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 2580e39e01cSJean Delvare &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 2590e39e01cSJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 2600e39e01cSJean Delvare &dev_attr_alarms.attr, 2610e39e01cSJean Delvare NULL 2620e39e01cSJean Delvare }; 2630e39e01cSJean Delvare 2640e39e01cSJean Delvare static const struct attribute_group lm83_group = { 2650e39e01cSJean Delvare .attrs = lm83_attributes, 2660e39e01cSJean Delvare }; 2670e39e01cSJean Delvare 2680e39e01cSJean Delvare static struct attribute *lm83_attributes_opt[] = { 2690e39e01cSJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 2700e39e01cSJean Delvare &sensor_dev_attr_temp4_input.dev_attr.attr, 2710e39e01cSJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 2720e39e01cSJean Delvare &sensor_dev_attr_temp4_max.dev_attr.attr, 2730e39e01cSJean Delvare &sensor_dev_attr_temp2_crit.dev_attr.attr, 2740e39e01cSJean Delvare &sensor_dev_attr_temp4_crit.dev_attr.attr, 2750e39e01cSJean Delvare 2760e39e01cSJean Delvare &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 2770e39e01cSJean Delvare &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, 2787817a39eSJean Delvare &sensor_dev_attr_temp4_fault.dev_attr.attr, 2790e39e01cSJean Delvare &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, 2807817a39eSJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 2810e39e01cSJean Delvare &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 2820e39e01cSJean Delvare NULL 2830e39e01cSJean Delvare }; 2840e39e01cSJean Delvare 2850e39e01cSJean Delvare static const struct attribute_group lm83_group_opt = { 2860e39e01cSJean Delvare .attrs = lm83_attributes_opt, 2870e39e01cSJean Delvare }; 2880e39e01cSJean Delvare 2898d5d45fbSJean Delvare /* 2908d5d45fbSJean Delvare * Real code 2918d5d45fbSJean Delvare */ 2928d5d45fbSJean Delvare 293b6aacdceSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */ 294310ec792SJean Delvare static int lm83_detect(struct i2c_client *new_client, 295b6aacdceSJean Delvare struct i2c_board_info *info) 2968d5d45fbSJean Delvare { 297b6aacdceSJean Delvare struct i2c_adapter *adapter = new_client->adapter; 298b57dc394SJean Delvare const char *name; 299b57dc394SJean Delvare u8 man_id, chip_id; 3008d5d45fbSJean Delvare 3018d5d45fbSJean Delvare if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 302b6aacdceSJean Delvare return -ENODEV; 3038d5d45fbSJean Delvare 304b57dc394SJean Delvare /* Detection */ 305b57dc394SJean Delvare if ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) || 306b57dc394SJean Delvare (i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2) & 0x48) || 307b57dc394SJean Delvare (i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41)) { 308b57dc394SJean Delvare dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n", 309b6aacdceSJean Delvare new_client->addr); 310b6aacdceSJean Delvare return -ENODEV; 3118d5d45fbSJean Delvare } 3128d5d45fbSJean Delvare 313b57dc394SJean Delvare /* Identification */ 314b57dc394SJean Delvare man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID); 315b57dc394SJean Delvare if (man_id != 0x01) /* National Semiconductor */ 316b6aacdceSJean Delvare return -ENODEV; 3178d5d45fbSJean Delvare 318b57dc394SJean Delvare chip_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_CHIP_ID); 319b57dc394SJean Delvare switch (chip_id) { 320b57dc394SJean Delvare case 0x03: 3218d5d45fbSJean Delvare name = "lm83"; 322b57dc394SJean Delvare break; 323b57dc394SJean Delvare case 0x01: 32443cb7ebeSJordan Crouse name = "lm82"; 325b57dc394SJean Delvare break; 326b57dc394SJean Delvare default: 327b57dc394SJean Delvare /* identification failed */ 328b57dc394SJean Delvare dev_info(&adapter->dev, 329b57dc394SJean Delvare "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n", 330b57dc394SJean Delvare man_id, chip_id); 331b57dc394SJean Delvare return -ENODEV; 3328d5d45fbSJean Delvare } 3338d5d45fbSJean Delvare 334b6aacdceSJean Delvare strlcpy(info->type, name, I2C_NAME_SIZE); 335b6aacdceSJean Delvare 336b6aacdceSJean Delvare return 0; 337b6aacdceSJean Delvare } 338b6aacdceSJean Delvare 339b6aacdceSJean Delvare static int lm83_probe(struct i2c_client *new_client, 340b6aacdceSJean Delvare const struct i2c_device_id *id) 341b6aacdceSJean Delvare { 342b6aacdceSJean Delvare struct lm83_data *data; 343b6aacdceSJean Delvare int err; 344b6aacdceSJean Delvare 345b6aacdceSJean Delvare data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL); 346b6aacdceSJean Delvare if (!data) { 347b6aacdceSJean Delvare err = -ENOMEM; 348b6aacdceSJean Delvare goto exit; 349b6aacdceSJean Delvare } 350b6aacdceSJean Delvare 351b6aacdceSJean Delvare i2c_set_clientdata(new_client, data); 3528d5d45fbSJean Delvare data->valid = 0; 3539a61bf63SIngo Molnar mutex_init(&data->update_lock); 3548d5d45fbSJean Delvare 3558d5d45fbSJean Delvare /* 3560e39e01cSJean Delvare * Register sysfs hooks 35743cb7ebeSJordan Crouse * The LM82 can only monitor one external diode which is 35843cb7ebeSJordan Crouse * at the same register as the LM83 temp3 entry - so we 35943cb7ebeSJordan Crouse * declare 1 and 3 common, and then 2 and 4 only for the LM83. 36043cb7ebeSJordan Crouse */ 36143cb7ebeSJordan Crouse 3620e39e01cSJean Delvare if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group))) 363b6aacdceSJean Delvare goto exit_free; 36443cb7ebeSJordan Crouse 365b6aacdceSJean Delvare if (id->driver_data == lm83) { 3660e39e01cSJean Delvare if ((err = sysfs_create_group(&new_client->dev.kobj, 3670e39e01cSJean Delvare &lm83_group_opt))) 3680e39e01cSJean Delvare goto exit_remove_files; 3690e39e01cSJean Delvare } 37043cb7ebeSJordan Crouse 3711beeffe4STony Jones data->hwmon_dev = hwmon_device_register(&new_client->dev); 3721beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) { 3731beeffe4STony Jones err = PTR_ERR(data->hwmon_dev); 3740e39e01cSJean Delvare goto exit_remove_files; 37543cb7ebeSJordan Crouse } 3768d5d45fbSJean Delvare 3778d5d45fbSJean Delvare return 0; 3788d5d45fbSJean Delvare 3790e39e01cSJean Delvare exit_remove_files: 3800e39e01cSJean Delvare sysfs_remove_group(&new_client->dev.kobj, &lm83_group); 3810e39e01cSJean Delvare sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); 3828d5d45fbSJean Delvare exit_free: 3838d5d45fbSJean Delvare kfree(data); 3848d5d45fbSJean Delvare exit: 3858d5d45fbSJean Delvare return err; 3868d5d45fbSJean Delvare } 3878d5d45fbSJean Delvare 388b6aacdceSJean Delvare static int lm83_remove(struct i2c_client *client) 3898d5d45fbSJean Delvare { 390943b0830SMark M. Hoffman struct lm83_data *data = i2c_get_clientdata(client); 3918d5d45fbSJean Delvare 3921beeffe4STony Jones hwmon_device_unregister(data->hwmon_dev); 3930e39e01cSJean Delvare sysfs_remove_group(&client->dev.kobj, &lm83_group); 3940e39e01cSJean Delvare sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); 395943b0830SMark M. Hoffman 396943b0830SMark M. Hoffman kfree(data); 3978d5d45fbSJean Delvare return 0; 3988d5d45fbSJean Delvare } 3998d5d45fbSJean Delvare 4008d5d45fbSJean Delvare static struct lm83_data *lm83_update_device(struct device *dev) 4018d5d45fbSJean Delvare { 4028d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 4038d5d45fbSJean Delvare struct lm83_data *data = i2c_get_clientdata(client); 4048d5d45fbSJean Delvare 4059a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4068d5d45fbSJean Delvare 4078d5d45fbSJean Delvare if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { 4088d5d45fbSJean Delvare int nr; 4098d5d45fbSJean Delvare 4108d5d45fbSJean Delvare dev_dbg(&client->dev, "Updating lm83 data.\n"); 4118d5d45fbSJean Delvare for (nr = 0; nr < 9; nr++) { 4128d5d45fbSJean Delvare data->temp[nr] = 4138d5d45fbSJean Delvare i2c_smbus_read_byte_data(client, 4148d5d45fbSJean Delvare LM83_REG_R_TEMP[nr]); 4158d5d45fbSJean Delvare } 4168d5d45fbSJean Delvare data->alarms = 4178d5d45fbSJean Delvare i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) 4188d5d45fbSJean Delvare + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) 4198d5d45fbSJean Delvare << 8); 4208d5d45fbSJean Delvare 4218d5d45fbSJean Delvare data->last_updated = jiffies; 4228d5d45fbSJean Delvare data->valid = 1; 4238d5d45fbSJean Delvare } 4248d5d45fbSJean Delvare 4259a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4268d5d45fbSJean Delvare 4278d5d45fbSJean Delvare return data; 4288d5d45fbSJean Delvare } 4298d5d45fbSJean Delvare 4308d5d45fbSJean Delvare static int __init sensors_lm83_init(void) 4318d5d45fbSJean Delvare { 4328d5d45fbSJean Delvare return i2c_add_driver(&lm83_driver); 4338d5d45fbSJean Delvare } 4348d5d45fbSJean Delvare 4358d5d45fbSJean Delvare static void __exit sensors_lm83_exit(void) 4368d5d45fbSJean Delvare { 4378d5d45fbSJean Delvare i2c_del_driver(&lm83_driver); 4388d5d45fbSJean Delvare } 4398d5d45fbSJean Delvare 4408d5d45fbSJean Delvare MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); 4418d5d45fbSJean Delvare MODULE_DESCRIPTION("LM83 driver"); 4428d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 4438d5d45fbSJean Delvare 4448d5d45fbSJean Delvare module_init(sensors_lm83_init); 4458d5d45fbSJean Delvare module_exit(sensors_lm83_exit); 446