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 54e5e9f44cSJean Delvare enum chips { lm83, lm82 }; 558d5d45fbSJean Delvare 568d5d45fbSJean Delvare /* 578d5d45fbSJean Delvare * The LM83 registers 588d5d45fbSJean Delvare * Manufacturer ID is 0x01 for National Semiconductor. 598d5d45fbSJean Delvare */ 608d5d45fbSJean Delvare 618d5d45fbSJean Delvare #define LM83_REG_R_MAN_ID 0xFE 628d5d45fbSJean Delvare #define LM83_REG_R_CHIP_ID 0xFF 638d5d45fbSJean Delvare #define LM83_REG_R_CONFIG 0x03 648d5d45fbSJean Delvare #define LM83_REG_W_CONFIG 0x09 658d5d45fbSJean Delvare #define LM83_REG_R_STATUS1 0x02 668d5d45fbSJean Delvare #define LM83_REG_R_STATUS2 0x35 678d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_TEMP 0x00 688d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_HIGH 0x05 698d5d45fbSJean Delvare #define LM83_REG_W_LOCAL_HIGH 0x0B 708d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_TEMP 0x30 718d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_HIGH 0x38 728d5d45fbSJean Delvare #define LM83_REG_W_REMOTE1_HIGH 0x50 738d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_TEMP 0x01 748d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_HIGH 0x07 758d5d45fbSJean Delvare #define LM83_REG_W_REMOTE2_HIGH 0x0D 768d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_TEMP 0x31 778d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_HIGH 0x3A 788d5d45fbSJean Delvare #define LM83_REG_W_REMOTE3_HIGH 0x52 798d5d45fbSJean Delvare #define LM83_REG_R_TCRIT 0x42 808d5d45fbSJean Delvare #define LM83_REG_W_TCRIT 0x5A 818d5d45fbSJean Delvare 828d5d45fbSJean Delvare /* 838d5d45fbSJean Delvare * Conversions and various macros 848d5d45fbSJean Delvare * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius. 858d5d45fbSJean Delvare */ 868d5d45fbSJean Delvare 878d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 888d5d45fbSJean Delvare #define TEMP_TO_REG(val) ((val) <= -128000 ? -128 : \ 898d5d45fbSJean Delvare (val) >= 127000 ? 127 : \ 908d5d45fbSJean Delvare (val) < 0 ? ((val) - 500) / 1000 : \ 918d5d45fbSJean Delvare ((val) + 500) / 1000) 928d5d45fbSJean Delvare 938d5d45fbSJean Delvare static const u8 LM83_REG_R_TEMP[] = { 948d5d45fbSJean Delvare LM83_REG_R_LOCAL_TEMP, 958d5d45fbSJean Delvare LM83_REG_R_REMOTE1_TEMP, 968d5d45fbSJean Delvare LM83_REG_R_REMOTE2_TEMP, 978d5d45fbSJean Delvare LM83_REG_R_REMOTE3_TEMP, 988d5d45fbSJean Delvare LM83_REG_R_LOCAL_HIGH, 998d5d45fbSJean Delvare LM83_REG_R_REMOTE1_HIGH, 1008d5d45fbSJean Delvare LM83_REG_R_REMOTE2_HIGH, 1018d5d45fbSJean Delvare LM83_REG_R_REMOTE3_HIGH, 1028d5d45fbSJean Delvare LM83_REG_R_TCRIT, 1038d5d45fbSJean Delvare }; 1048d5d45fbSJean Delvare 1058d5d45fbSJean Delvare static const u8 LM83_REG_W_HIGH[] = { 1068d5d45fbSJean Delvare LM83_REG_W_LOCAL_HIGH, 1078d5d45fbSJean Delvare LM83_REG_W_REMOTE1_HIGH, 1088d5d45fbSJean Delvare LM83_REG_W_REMOTE2_HIGH, 1098d5d45fbSJean Delvare LM83_REG_W_REMOTE3_HIGH, 1108d5d45fbSJean Delvare LM83_REG_W_TCRIT, 1118d5d45fbSJean Delvare }; 1128d5d45fbSJean Delvare 1138d5d45fbSJean Delvare /* 1148d5d45fbSJean Delvare * Functions declaration 1158d5d45fbSJean Delvare */ 1168d5d45fbSJean Delvare 117310ec792SJean Delvare static int lm83_detect(struct i2c_client *new_client, 118b6aacdceSJean Delvare struct i2c_board_info *info); 119b6aacdceSJean Delvare static int lm83_probe(struct i2c_client *client, 120b6aacdceSJean Delvare const struct i2c_device_id *id); 121b6aacdceSJean Delvare static int lm83_remove(struct i2c_client *client); 1228d5d45fbSJean Delvare static struct lm83_data *lm83_update_device(struct device *dev); 1238d5d45fbSJean Delvare 1248d5d45fbSJean Delvare /* 1258d5d45fbSJean Delvare * Driver data (common to all clients) 1268d5d45fbSJean Delvare */ 1278d5d45fbSJean Delvare 128b6aacdceSJean Delvare static const struct i2c_device_id lm83_id[] = { 129b6aacdceSJean Delvare { "lm83", lm83 }, 130b6aacdceSJean Delvare { "lm82", lm82 }, 131b6aacdceSJean Delvare { } 132b6aacdceSJean Delvare }; 133b6aacdceSJean Delvare MODULE_DEVICE_TABLE(i2c, lm83_id); 134b6aacdceSJean Delvare 1358d5d45fbSJean Delvare static struct i2c_driver lm83_driver = { 136b6aacdceSJean Delvare .class = I2C_CLASS_HWMON, 137cdaf7934SLaurent Riffard .driver = { 1388d5d45fbSJean Delvare .name = "lm83", 139cdaf7934SLaurent Riffard }, 140b6aacdceSJean Delvare .probe = lm83_probe, 141b6aacdceSJean Delvare .remove = lm83_remove, 142b6aacdceSJean Delvare .id_table = lm83_id, 143b6aacdceSJean Delvare .detect = lm83_detect, 144c3813d6aSJean Delvare .address_list = normal_i2c, 1458d5d45fbSJean Delvare }; 1468d5d45fbSJean Delvare 1478d5d45fbSJean Delvare /* 1488d5d45fbSJean Delvare * Client data (each client gets its own) 1498d5d45fbSJean Delvare */ 1508d5d45fbSJean Delvare 1518d5d45fbSJean Delvare struct lm83_data { 1521beeffe4STony Jones struct device *hwmon_dev; 1539a61bf63SIngo Molnar struct mutex update_lock; 1548d5d45fbSJean Delvare char valid; /* zero until following fields are valid */ 1558d5d45fbSJean Delvare unsigned long last_updated; /* in jiffies */ 1568d5d45fbSJean Delvare 1578d5d45fbSJean Delvare /* registers values */ 1588d5d45fbSJean Delvare s8 temp[9]; /* 0..3: input 1-4, 1598d5d45fbSJean Delvare 4..7: high limit 1-4, 1608d5d45fbSJean Delvare 8 : critical limit */ 1618d5d45fbSJean Delvare u16 alarms; /* bitvector, combined */ 1628d5d45fbSJean Delvare }; 1638d5d45fbSJean Delvare 1648d5d45fbSJean Delvare /* 1658d5d45fbSJean Delvare * Sysfs stuff 1668d5d45fbSJean Delvare */ 1678d5d45fbSJean Delvare 1688d5d45fbSJean Delvare static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 1698d5d45fbSJean Delvare char *buf) 1708d5d45fbSJean Delvare { 1718d5d45fbSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1728d5d45fbSJean Delvare struct lm83_data *data = lm83_update_device(dev); 1738d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); 1748d5d45fbSJean Delvare } 1758d5d45fbSJean Delvare 1768d5d45fbSJean Delvare static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, 1778d5d45fbSJean Delvare const char *buf, size_t count) 1788d5d45fbSJean Delvare { 1798d5d45fbSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1808d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 1818d5d45fbSJean Delvare struct lm83_data *data = i2c_get_clientdata(client); 182b3789a0dSFrans Meulenbroeks long val; 1838d5d45fbSJean Delvare int nr = attr->index; 184b3789a0dSFrans Meulenbroeks int err; 185b3789a0dSFrans Meulenbroeks 186b3789a0dSFrans Meulenbroeks err = kstrtol(buf, 10, &val); 187b3789a0dSFrans Meulenbroeks if (err < 0) 188b3789a0dSFrans Meulenbroeks return err; 1898d5d45fbSJean Delvare 1909a61bf63SIngo Molnar mutex_lock(&data->update_lock); 1918d5d45fbSJean Delvare data->temp[nr] = TEMP_TO_REG(val); 1928d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], 1938d5d45fbSJean Delvare data->temp[nr]); 1949a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 1958d5d45fbSJean Delvare return count; 1968d5d45fbSJean Delvare } 1978d5d45fbSJean Delvare 1988d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, 1998d5d45fbSJean Delvare char *buf) 2008d5d45fbSJean Delvare { 2018d5d45fbSJean Delvare struct lm83_data *data = lm83_update_device(dev); 2028d5d45fbSJean Delvare return sprintf(buf, "%d\n", data->alarms); 2038d5d45fbSJean Delvare } 2048d5d45fbSJean Delvare 2052d45771eSJean Delvare static ssize_t show_alarm(struct device *dev, struct device_attribute 2062d45771eSJean Delvare *devattr, char *buf) 2072d45771eSJean Delvare { 2082d45771eSJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 2092d45771eSJean Delvare struct lm83_data *data = lm83_update_device(dev); 2102d45771eSJean Delvare int bitnr = attr->index; 2112d45771eSJean Delvare 2122d45771eSJean Delvare return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); 2132d45771eSJean Delvare } 2142d45771eSJean Delvare 2158d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 2168d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); 2178d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); 2188d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); 2198d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, 2208d5d45fbSJean Delvare set_temp, 4); 2218d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, 2228d5d45fbSJean Delvare set_temp, 5); 2238d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp, 2248d5d45fbSJean Delvare set_temp, 6); 2258d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp, 2268d5d45fbSJean Delvare set_temp, 7); 2278d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8); 2288d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8); 2298d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, 2308d5d45fbSJean Delvare set_temp, 8); 2318d5d45fbSJean Delvare static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); 2322d45771eSJean Delvare 2332d45771eSJean Delvare /* Individual alarm files */ 2342d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); 2352d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); 2367817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); 2372d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); 2382d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); 2392d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); 2402d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); 2417817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10); 2422d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); 2437817a39eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13); 2442d45771eSJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); 2452d45771eSJean Delvare /* Raw alarm file for compatibility */ 2468d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 2478d5d45fbSJean Delvare 2480e39e01cSJean Delvare static struct attribute *lm83_attributes[] = { 2490e39e01cSJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 2500e39e01cSJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 2510e39e01cSJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 2520e39e01cSJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 2530e39e01cSJean Delvare &sensor_dev_attr_temp1_crit.dev_attr.attr, 2540e39e01cSJean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 2550e39e01cSJean Delvare 2560e39e01cSJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 2570e39e01cSJean Delvare &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 2587817a39eSJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 2590e39e01cSJean Delvare &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 2600e39e01cSJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 2610e39e01cSJean Delvare &dev_attr_alarms.attr, 2620e39e01cSJean Delvare NULL 2630e39e01cSJean Delvare }; 2640e39e01cSJean Delvare 2650e39e01cSJean Delvare static const struct attribute_group lm83_group = { 2660e39e01cSJean Delvare .attrs = lm83_attributes, 2670e39e01cSJean Delvare }; 2680e39e01cSJean Delvare 2690e39e01cSJean Delvare static struct attribute *lm83_attributes_opt[] = { 2700e39e01cSJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 2710e39e01cSJean Delvare &sensor_dev_attr_temp4_input.dev_attr.attr, 2720e39e01cSJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 2730e39e01cSJean Delvare &sensor_dev_attr_temp4_max.dev_attr.attr, 2740e39e01cSJean Delvare &sensor_dev_attr_temp2_crit.dev_attr.attr, 2750e39e01cSJean Delvare &sensor_dev_attr_temp4_crit.dev_attr.attr, 2760e39e01cSJean Delvare 2770e39e01cSJean Delvare &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 2780e39e01cSJean Delvare &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, 2797817a39eSJean Delvare &sensor_dev_attr_temp4_fault.dev_attr.attr, 2800e39e01cSJean Delvare &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, 2817817a39eSJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 2820e39e01cSJean Delvare &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 2830e39e01cSJean Delvare NULL 2840e39e01cSJean Delvare }; 2850e39e01cSJean Delvare 2860e39e01cSJean Delvare static const struct attribute_group lm83_group_opt = { 2870e39e01cSJean Delvare .attrs = lm83_attributes_opt, 2880e39e01cSJean Delvare }; 2890e39e01cSJean Delvare 2908d5d45fbSJean Delvare /* 2918d5d45fbSJean Delvare * Real code 2928d5d45fbSJean Delvare */ 2938d5d45fbSJean Delvare 294b6aacdceSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */ 295310ec792SJean Delvare static int lm83_detect(struct i2c_client *new_client, 296b6aacdceSJean Delvare struct i2c_board_info *info) 2978d5d45fbSJean Delvare { 298b6aacdceSJean Delvare struct i2c_adapter *adapter = new_client->adapter; 299b57dc394SJean Delvare const char *name; 300b57dc394SJean Delvare u8 man_id, chip_id; 3018d5d45fbSJean Delvare 3028d5d45fbSJean Delvare if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 303b6aacdceSJean Delvare return -ENODEV; 3048d5d45fbSJean Delvare 305b57dc394SJean Delvare /* Detection */ 306b57dc394SJean Delvare if ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) || 307b57dc394SJean Delvare (i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2) & 0x48) || 308b57dc394SJean Delvare (i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41)) { 309b57dc394SJean Delvare dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n", 310b6aacdceSJean Delvare new_client->addr); 311b6aacdceSJean Delvare return -ENODEV; 3128d5d45fbSJean Delvare } 3138d5d45fbSJean Delvare 314b57dc394SJean Delvare /* Identification */ 315b57dc394SJean Delvare man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID); 316b57dc394SJean Delvare if (man_id != 0x01) /* National Semiconductor */ 317b6aacdceSJean Delvare return -ENODEV; 3188d5d45fbSJean Delvare 319b57dc394SJean Delvare chip_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_CHIP_ID); 320b57dc394SJean Delvare switch (chip_id) { 321b57dc394SJean Delvare case 0x03: 3228d5d45fbSJean Delvare name = "lm83"; 323b57dc394SJean Delvare break; 324b57dc394SJean Delvare case 0x01: 32543cb7ebeSJordan Crouse name = "lm82"; 326b57dc394SJean Delvare break; 327b57dc394SJean Delvare default: 328b57dc394SJean Delvare /* identification failed */ 329b57dc394SJean Delvare dev_info(&adapter->dev, 330b57dc394SJean Delvare "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n", 331b57dc394SJean Delvare man_id, chip_id); 332b57dc394SJean Delvare return -ENODEV; 3338d5d45fbSJean Delvare } 3348d5d45fbSJean Delvare 335b6aacdceSJean Delvare strlcpy(info->type, name, I2C_NAME_SIZE); 336b6aacdceSJean Delvare 337b6aacdceSJean Delvare return 0; 338b6aacdceSJean Delvare } 339b6aacdceSJean Delvare 340b6aacdceSJean Delvare static int lm83_probe(struct i2c_client *new_client, 341b6aacdceSJean Delvare const struct i2c_device_id *id) 342b6aacdceSJean Delvare { 343b6aacdceSJean Delvare struct lm83_data *data; 344b6aacdceSJean Delvare int err; 345b6aacdceSJean Delvare 346b6aacdceSJean Delvare data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL); 347b6aacdceSJean Delvare if (!data) { 348b6aacdceSJean Delvare err = -ENOMEM; 349b6aacdceSJean Delvare goto exit; 350b6aacdceSJean Delvare } 351b6aacdceSJean Delvare 352b6aacdceSJean Delvare i2c_set_clientdata(new_client, data); 3538d5d45fbSJean Delvare data->valid = 0; 3549a61bf63SIngo Molnar mutex_init(&data->update_lock); 3558d5d45fbSJean Delvare 3568d5d45fbSJean Delvare /* 3570e39e01cSJean Delvare * Register sysfs hooks 35843cb7ebeSJordan Crouse * The LM82 can only monitor one external diode which is 35943cb7ebeSJordan Crouse * at the same register as the LM83 temp3 entry - so we 36043cb7ebeSJordan Crouse * declare 1 and 3 common, and then 2 and 4 only for the LM83. 36143cb7ebeSJordan Crouse */ 36243cb7ebeSJordan Crouse 363b3789a0dSFrans Meulenbroeks err = sysfs_create_group(&new_client->dev.kobj, &lm83_group); 364b3789a0dSFrans Meulenbroeks if (err) 365b6aacdceSJean Delvare goto exit_free; 36643cb7ebeSJordan Crouse 367b6aacdceSJean Delvare if (id->driver_data == lm83) { 368b3789a0dSFrans Meulenbroeks err = sysfs_create_group(&new_client->dev.kobj, 369b3789a0dSFrans Meulenbroeks &lm83_group_opt); 370b3789a0dSFrans Meulenbroeks if (err) 3710e39e01cSJean Delvare goto exit_remove_files; 3720e39e01cSJean Delvare } 37343cb7ebeSJordan Crouse 3741beeffe4STony Jones data->hwmon_dev = hwmon_device_register(&new_client->dev); 3751beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) { 3761beeffe4STony Jones err = PTR_ERR(data->hwmon_dev); 3770e39e01cSJean Delvare goto exit_remove_files; 37843cb7ebeSJordan Crouse } 3798d5d45fbSJean Delvare 3808d5d45fbSJean Delvare return 0; 3818d5d45fbSJean Delvare 3820e39e01cSJean Delvare exit_remove_files: 3830e39e01cSJean Delvare sysfs_remove_group(&new_client->dev.kobj, &lm83_group); 3840e39e01cSJean Delvare sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); 3858d5d45fbSJean Delvare exit_free: 3868d5d45fbSJean Delvare kfree(data); 3878d5d45fbSJean Delvare exit: 3888d5d45fbSJean Delvare return err; 3898d5d45fbSJean Delvare } 3908d5d45fbSJean Delvare 391b6aacdceSJean Delvare static int lm83_remove(struct i2c_client *client) 3928d5d45fbSJean Delvare { 393943b0830SMark M. Hoffman struct lm83_data *data = i2c_get_clientdata(client); 3948d5d45fbSJean Delvare 3951beeffe4STony Jones hwmon_device_unregister(data->hwmon_dev); 3960e39e01cSJean Delvare sysfs_remove_group(&client->dev.kobj, &lm83_group); 3970e39e01cSJean Delvare sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); 398943b0830SMark M. Hoffman 399943b0830SMark M. Hoffman kfree(data); 4008d5d45fbSJean Delvare return 0; 4018d5d45fbSJean Delvare } 4028d5d45fbSJean Delvare 4038d5d45fbSJean Delvare static struct lm83_data *lm83_update_device(struct device *dev) 4048d5d45fbSJean Delvare { 4058d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 4068d5d45fbSJean Delvare struct lm83_data *data = i2c_get_clientdata(client); 4078d5d45fbSJean Delvare 4089a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4098d5d45fbSJean Delvare 4108d5d45fbSJean Delvare if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { 4118d5d45fbSJean Delvare int nr; 4128d5d45fbSJean Delvare 4138d5d45fbSJean Delvare dev_dbg(&client->dev, "Updating lm83 data.\n"); 4148d5d45fbSJean Delvare for (nr = 0; nr < 9; nr++) { 4158d5d45fbSJean Delvare data->temp[nr] = 4168d5d45fbSJean Delvare i2c_smbus_read_byte_data(client, 4178d5d45fbSJean Delvare LM83_REG_R_TEMP[nr]); 4188d5d45fbSJean Delvare } 4198d5d45fbSJean Delvare data->alarms = 4208d5d45fbSJean Delvare i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) 4218d5d45fbSJean Delvare + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) 4228d5d45fbSJean Delvare << 8); 4238d5d45fbSJean Delvare 4248d5d45fbSJean Delvare data->last_updated = jiffies; 4258d5d45fbSJean Delvare data->valid = 1; 4268d5d45fbSJean Delvare } 4278d5d45fbSJean Delvare 4289a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4298d5d45fbSJean Delvare 4308d5d45fbSJean Delvare return data; 4318d5d45fbSJean Delvare } 4328d5d45fbSJean Delvare 433f0967eeaSAxel Lin module_i2c_driver(lm83_driver); 4348d5d45fbSJean Delvare 4358d5d45fbSJean Delvare MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); 4368d5d45fbSJean Delvare MODULE_DESCRIPTION("LM83 driver"); 4378d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 438