xref: /openbmc/linux/drivers/hwmon/lm83.c (revision 81de0eea)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28d5d45fbSJean Delvare /*
38d5d45fbSJean Delvare  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
48d5d45fbSJean Delvare  *          monitoring
57c81c60fSJean Delvare  * Copyright (C) 2003-2009  Jean Delvare <jdelvare@suse.de>
68d5d45fbSJean Delvare  *
78d5d45fbSJean Delvare  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
88d5d45fbSJean Delvare  * a sensor chip made by National Semiconductor. It reports up to four
98d5d45fbSJean Delvare  * temperatures (its own plus up to three external ones) with a 1 deg
108d5d45fbSJean Delvare  * resolution and a 3-4 deg accuracy. Complete datasheet can be obtained
118d5d45fbSJean Delvare  * from National's website at:
128d5d45fbSJean Delvare  *   http://www.national.com/pf/LM/LM83.html
138d5d45fbSJean Delvare  * Since the datasheet omits to give the chip stepping code, I give it
148d5d45fbSJean Delvare  * here: 0x03 (at register 0xff).
158d5d45fbSJean Delvare  *
1643cb7ebeSJordan Crouse  * Also supports the LM82 temp sensor, which is basically a stripped down
1743cb7ebeSJordan Crouse  * model of the LM83.  Datasheet is here:
1843cb7ebeSJordan Crouse  * http://www.national.com/pf/LM/LM82.html
198d5d45fbSJean Delvare  */
208d5d45fbSJean Delvare 
21943b0830SMark M. Hoffman #include <linux/err.h>
227c68c2c7SGuenter Roeck #include <linux/i2c.h>
237c68c2c7SGuenter Roeck #include <linux/init.h>
247c68c2c7SGuenter Roeck #include <linux/jiffies.h>
257c68c2c7SGuenter Roeck #include <linux/hwmon.h>
267c68c2c7SGuenter Roeck #include <linux/hwmon-sysfs.h>
277c68c2c7SGuenter Roeck #include <linux/module.h>
289a61bf63SIngo Molnar #include <linux/mutex.h>
297c68c2c7SGuenter Roeck #include <linux/slab.h>
300e39e01cSJean Delvare #include <linux/sysfs.h>
318d5d45fbSJean Delvare 
328d5d45fbSJean Delvare /*
338d5d45fbSJean Delvare  * Addresses to scan
348d5d45fbSJean Delvare  * Address is selected using 2 three-level pins, resulting in 9 possible
358d5d45fbSJean Delvare  * addresses.
368d5d45fbSJean Delvare  */
378d5d45fbSJean Delvare 
3825e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = {
3925e9c86dSMark M. Hoffman 	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
408d5d45fbSJean Delvare 
41e5e9f44cSJean Delvare enum chips { lm83, lm82 };
428d5d45fbSJean Delvare 
438d5d45fbSJean Delvare /*
448d5d45fbSJean Delvare  * The LM83 registers
458d5d45fbSJean Delvare  * Manufacturer ID is 0x01 for National Semiconductor.
468d5d45fbSJean Delvare  */
478d5d45fbSJean Delvare 
488d5d45fbSJean Delvare #define LM83_REG_R_MAN_ID		0xFE
498d5d45fbSJean Delvare #define LM83_REG_R_CHIP_ID		0xFF
508d5d45fbSJean Delvare #define LM83_REG_R_CONFIG		0x03
518d5d45fbSJean Delvare #define LM83_REG_W_CONFIG		0x09
528d5d45fbSJean Delvare #define LM83_REG_R_STATUS1		0x02
538d5d45fbSJean Delvare #define LM83_REG_R_STATUS2		0x35
548d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_TEMP		0x00
558d5d45fbSJean Delvare #define LM83_REG_R_LOCAL_HIGH		0x05
568d5d45fbSJean Delvare #define LM83_REG_W_LOCAL_HIGH		0x0B
578d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_TEMP		0x30
588d5d45fbSJean Delvare #define LM83_REG_R_REMOTE1_HIGH		0x38
598d5d45fbSJean Delvare #define LM83_REG_W_REMOTE1_HIGH		0x50
608d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_TEMP		0x01
618d5d45fbSJean Delvare #define LM83_REG_R_REMOTE2_HIGH		0x07
628d5d45fbSJean Delvare #define LM83_REG_W_REMOTE2_HIGH		0x0D
638d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_TEMP		0x31
648d5d45fbSJean Delvare #define LM83_REG_R_REMOTE3_HIGH		0x3A
658d5d45fbSJean Delvare #define LM83_REG_W_REMOTE3_HIGH		0x52
668d5d45fbSJean Delvare #define LM83_REG_R_TCRIT		0x42
678d5d45fbSJean Delvare #define LM83_REG_W_TCRIT		0x5A
688d5d45fbSJean Delvare 
698d5d45fbSJean Delvare /*
708d5d45fbSJean Delvare  * Conversions and various macros
718d5d45fbSJean Delvare  * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius.
728d5d45fbSJean Delvare  */
738d5d45fbSJean Delvare 
748d5d45fbSJean Delvare #define TEMP_FROM_REG(val)	((val) * 1000)
758d5d45fbSJean Delvare #define TEMP_TO_REG(val)	((val) <= -128000 ? -128 : \
768d5d45fbSJean Delvare 				 (val) >= 127000 ? 127 : \
778d5d45fbSJean Delvare 				 (val) < 0 ? ((val) - 500) / 1000 : \
788d5d45fbSJean Delvare 				 ((val) + 500) / 1000)
798d5d45fbSJean Delvare 
808d5d45fbSJean Delvare static const u8 LM83_REG_R_TEMP[] = {
818d5d45fbSJean Delvare 	LM83_REG_R_LOCAL_TEMP,
828d5d45fbSJean Delvare 	LM83_REG_R_REMOTE1_TEMP,
838d5d45fbSJean Delvare 	LM83_REG_R_REMOTE2_TEMP,
848d5d45fbSJean Delvare 	LM83_REG_R_REMOTE3_TEMP,
858d5d45fbSJean Delvare 	LM83_REG_R_LOCAL_HIGH,
868d5d45fbSJean Delvare 	LM83_REG_R_REMOTE1_HIGH,
878d5d45fbSJean Delvare 	LM83_REG_R_REMOTE2_HIGH,
888d5d45fbSJean Delvare 	LM83_REG_R_REMOTE3_HIGH,
898d5d45fbSJean Delvare 	LM83_REG_R_TCRIT,
908d5d45fbSJean Delvare };
918d5d45fbSJean Delvare 
928d5d45fbSJean Delvare static const u8 LM83_REG_W_HIGH[] = {
938d5d45fbSJean Delvare 	LM83_REG_W_LOCAL_HIGH,
948d5d45fbSJean Delvare 	LM83_REG_W_REMOTE1_HIGH,
958d5d45fbSJean Delvare 	LM83_REG_W_REMOTE2_HIGH,
968d5d45fbSJean Delvare 	LM83_REG_W_REMOTE3_HIGH,
978d5d45fbSJean Delvare 	LM83_REG_W_TCRIT,
988d5d45fbSJean Delvare };
998d5d45fbSJean Delvare 
1008d5d45fbSJean Delvare /*
1018d5d45fbSJean Delvare  * Client data (each client gets its own)
1028d5d45fbSJean Delvare  */
1038d5d45fbSJean Delvare 
1048d5d45fbSJean Delvare struct lm83_data {
105a0ac840dSGuenter Roeck 	struct i2c_client *client;
106a0ac840dSGuenter Roeck 	const struct attribute_group *groups[3];
1079a61bf63SIngo Molnar 	struct mutex update_lock;
108952a11caSPaul Fertser 	bool valid; /* false until following fields are valid */
1098d5d45fbSJean Delvare 	unsigned long last_updated; /* in jiffies */
1108d5d45fbSJean Delvare 
1118d5d45fbSJean Delvare 	/* registers values */
1128d5d45fbSJean Delvare 	s8 temp[9];	/* 0..3: input 1-4,
1138d5d45fbSJean Delvare 			   4..7: high limit 1-4,
1148d5d45fbSJean Delvare 			   8   : critical limit */
1158d5d45fbSJean Delvare 	u16 alarms; /* bitvector, combined */
1168d5d45fbSJean Delvare };
1178d5d45fbSJean Delvare 
11841936370SGuenter Roeck static struct lm83_data *lm83_update_device(struct device *dev)
11941936370SGuenter Roeck {
120a0ac840dSGuenter Roeck 	struct lm83_data *data = dev_get_drvdata(dev);
121a0ac840dSGuenter Roeck 	struct i2c_client *client = data->client;
12241936370SGuenter Roeck 
12341936370SGuenter Roeck 	mutex_lock(&data->update_lock);
12441936370SGuenter Roeck 
12541936370SGuenter Roeck 	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
12641936370SGuenter Roeck 		int nr;
12741936370SGuenter Roeck 
12841936370SGuenter Roeck 		dev_dbg(&client->dev, "Updating lm83 data.\n");
12941936370SGuenter Roeck 		for (nr = 0; nr < 9; nr++) {
13041936370SGuenter Roeck 			data->temp[nr] =
13141936370SGuenter Roeck 			    i2c_smbus_read_byte_data(client,
13241936370SGuenter Roeck 			    LM83_REG_R_TEMP[nr]);
13341936370SGuenter Roeck 		}
13441936370SGuenter Roeck 		data->alarms =
13541936370SGuenter Roeck 		    i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
13641936370SGuenter Roeck 		    + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
13741936370SGuenter Roeck 		    << 8);
13841936370SGuenter Roeck 
13941936370SGuenter Roeck 		data->last_updated = jiffies;
140952a11caSPaul Fertser 		data->valid = true;
14141936370SGuenter Roeck 	}
14241936370SGuenter Roeck 
14341936370SGuenter Roeck 	mutex_unlock(&data->update_lock);
14441936370SGuenter Roeck 
14541936370SGuenter Roeck 	return data;
14641936370SGuenter Roeck }
14741936370SGuenter Roeck 
1488d5d45fbSJean Delvare /*
1498d5d45fbSJean Delvare  * Sysfs stuff
1508d5d45fbSJean Delvare  */
1518d5d45fbSJean Delvare 
152a9283c8fSGuenter Roeck static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
1538d5d45fbSJean Delvare 			 char *buf)
1548d5d45fbSJean Delvare {
1558d5d45fbSJean Delvare 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1568d5d45fbSJean Delvare 	struct lm83_data *data = lm83_update_device(dev);
1578d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
1588d5d45fbSJean Delvare }
1598d5d45fbSJean Delvare 
160a9283c8fSGuenter Roeck static ssize_t temp_store(struct device *dev,
161a9283c8fSGuenter Roeck 			  struct device_attribute *devattr, const char *buf,
162a9283c8fSGuenter Roeck 			  size_t count)
1638d5d45fbSJean Delvare {
1648d5d45fbSJean Delvare 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
165a0ac840dSGuenter Roeck 	struct lm83_data *data = dev_get_drvdata(dev);
166a0ac840dSGuenter Roeck 	struct i2c_client *client = data->client;
167b3789a0dSFrans Meulenbroeks 	long val;
1688d5d45fbSJean Delvare 	int nr = attr->index;
169b3789a0dSFrans Meulenbroeks 	int err;
170b3789a0dSFrans Meulenbroeks 
171b3789a0dSFrans Meulenbroeks 	err = kstrtol(buf, 10, &val);
172b3789a0dSFrans Meulenbroeks 	if (err < 0)
173b3789a0dSFrans Meulenbroeks 		return err;
1748d5d45fbSJean Delvare 
1759a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
1768d5d45fbSJean Delvare 	data->temp[nr] = TEMP_TO_REG(val);
1778d5d45fbSJean Delvare 	i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4],
1788d5d45fbSJean Delvare 				  data->temp[nr]);
1799a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
1808d5d45fbSJean Delvare 	return count;
1818d5d45fbSJean Delvare }
1828d5d45fbSJean Delvare 
18314c05198SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *dummy,
1848d5d45fbSJean Delvare 			   char *buf)
1858d5d45fbSJean Delvare {
1868d5d45fbSJean Delvare 	struct lm83_data *data = lm83_update_device(dev);
1878d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarms);
1888d5d45fbSJean Delvare }
1898d5d45fbSJean Delvare 
190a9283c8fSGuenter Roeck static ssize_t alarm_show(struct device *dev,
191a9283c8fSGuenter Roeck 			  struct device_attribute *devattr, char *buf)
1922d45771eSJean Delvare {
1932d45771eSJean Delvare 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1942d45771eSJean Delvare 	struct lm83_data *data = lm83_update_device(dev);
1952d45771eSJean Delvare 	int bitnr = attr->index;
1962d45771eSJean Delvare 
1972d45771eSJean Delvare 	return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
1982d45771eSJean Delvare }
1992d45771eSJean Delvare 
200a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
201a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
202a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
203a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 3);
204a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 4);
205a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, 5);
206a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_max, temp, 6);
207a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp4_max, temp, 7);
208a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp, 8);
209a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp, 8);
210a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp, 8);
211a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp, 8);
2122d45771eSJean Delvare 
2132d45771eSJean Delvare /* Individual alarm files */
214a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0);
215a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 1);
216a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
217a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 4);
218a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
219a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
220a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 9);
221a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp4_fault, alarm, 10);
222a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, alarm, 12);
223a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 13);
224a9283c8fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 15);
2252d45771eSJean Delvare /* Raw alarm file for compatibility */
22614c05198SJulia Lawall static DEVICE_ATTR_RO(alarms);
2278d5d45fbSJean Delvare 
2280e39e01cSJean Delvare static struct attribute *lm83_attributes[] = {
2290e39e01cSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
2300e39e01cSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
2310e39e01cSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
2320e39e01cSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
2330e39e01cSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
2340e39e01cSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
2350e39e01cSJean Delvare 
2360e39e01cSJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
2370e39e01cSJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
2387817a39eSJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
2390e39e01cSJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
2400e39e01cSJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
2410e39e01cSJean Delvare 	&dev_attr_alarms.attr,
2420e39e01cSJean Delvare 	NULL
2430e39e01cSJean Delvare };
2440e39e01cSJean Delvare 
2450e39e01cSJean Delvare static const struct attribute_group lm83_group = {
2460e39e01cSJean Delvare 	.attrs = lm83_attributes,
2470e39e01cSJean Delvare };
2480e39e01cSJean Delvare 
2490e39e01cSJean Delvare static struct attribute *lm83_attributes_opt[] = {
2500e39e01cSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
2510e39e01cSJean Delvare 	&sensor_dev_attr_temp4_input.dev_attr.attr,
2520e39e01cSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
2530e39e01cSJean Delvare 	&sensor_dev_attr_temp4_max.dev_attr.attr,
2540e39e01cSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
2550e39e01cSJean Delvare 	&sensor_dev_attr_temp4_crit.dev_attr.attr,
2560e39e01cSJean Delvare 
2570e39e01cSJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
2580e39e01cSJean Delvare 	&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
2597817a39eSJean Delvare 	&sensor_dev_attr_temp4_fault.dev_attr.attr,
2600e39e01cSJean Delvare 	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
2617817a39eSJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
2620e39e01cSJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
2630e39e01cSJean Delvare 	NULL
2640e39e01cSJean Delvare };
2650e39e01cSJean Delvare 
2660e39e01cSJean Delvare static const struct attribute_group lm83_group_opt = {
2670e39e01cSJean Delvare 	.attrs = lm83_attributes_opt,
2680e39e01cSJean Delvare };
2690e39e01cSJean Delvare 
2708d5d45fbSJean Delvare /*
2718d5d45fbSJean Delvare  * Real code
2728d5d45fbSJean Delvare  */
2738d5d45fbSJean Delvare 
274b6aacdceSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
275*81de0eeaSGuenter Roeck static int lm83_detect(struct i2c_client *client,
276b6aacdceSJean Delvare 		       struct i2c_board_info *info)
2778d5d45fbSJean Delvare {
278*81de0eeaSGuenter Roeck 	struct i2c_adapter *adapter = client->adapter;
279b57dc394SJean Delvare 	const char *name;
280b57dc394SJean Delvare 	u8 man_id, chip_id;
2818d5d45fbSJean Delvare 
2828d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
283b6aacdceSJean Delvare 		return -ENODEV;
2848d5d45fbSJean Delvare 
285b57dc394SJean Delvare 	/* Detection */
286*81de0eeaSGuenter Roeck 	if ((i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) & 0xA8) ||
287*81de0eeaSGuenter Roeck 	    (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) & 0x48) ||
288*81de0eeaSGuenter Roeck 	    (i2c_smbus_read_byte_data(client, LM83_REG_R_CONFIG) & 0x41)) {
289b57dc394SJean Delvare 		dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n",
290*81de0eeaSGuenter Roeck 			client->addr);
291b6aacdceSJean Delvare 		return -ENODEV;
2928d5d45fbSJean Delvare 	}
2938d5d45fbSJean Delvare 
294b57dc394SJean Delvare 	/* Identification */
295*81de0eeaSGuenter Roeck 	man_id = i2c_smbus_read_byte_data(client, LM83_REG_R_MAN_ID);
296b57dc394SJean Delvare 	if (man_id != 0x01)	/* National Semiconductor */
297b6aacdceSJean Delvare 		return -ENODEV;
2988d5d45fbSJean Delvare 
299*81de0eeaSGuenter Roeck 	chip_id = i2c_smbus_read_byte_data(client, LM83_REG_R_CHIP_ID);
300b57dc394SJean Delvare 	switch (chip_id) {
301b57dc394SJean Delvare 	case 0x03:
3028d5d45fbSJean Delvare 		name = "lm83";
303b57dc394SJean Delvare 		break;
304b57dc394SJean Delvare 	case 0x01:
30543cb7ebeSJordan Crouse 		name = "lm82";
306b57dc394SJean Delvare 		break;
307b57dc394SJean Delvare 	default:
308b57dc394SJean Delvare 		/* identification failed */
309b57dc394SJean Delvare 		dev_info(&adapter->dev,
310b57dc394SJean Delvare 			 "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n",
311b57dc394SJean Delvare 			 man_id, chip_id);
312b57dc394SJean Delvare 		return -ENODEV;
3138d5d45fbSJean Delvare 	}
3148d5d45fbSJean Delvare 
315b6aacdceSJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
316b6aacdceSJean Delvare 
317b6aacdceSJean Delvare 	return 0;
318b6aacdceSJean Delvare }
319b6aacdceSJean Delvare 
32011e3377bSGuenter Roeck static const struct i2c_device_id lm83_id[] = {
32111e3377bSGuenter Roeck 	{ "lm83", lm83 },
32211e3377bSGuenter Roeck 	{ "lm82", lm82 },
32311e3377bSGuenter Roeck 	{ }
32411e3377bSGuenter Roeck };
32511e3377bSGuenter Roeck MODULE_DEVICE_TABLE(i2c, lm83_id);
32667487038SStephen Kitt 
327*81de0eeaSGuenter Roeck static int lm83_probe(struct i2c_client *client)
328b6aacdceSJean Delvare {
329a0ac840dSGuenter Roeck 	struct device *hwmon_dev;
330b6aacdceSJean Delvare 	struct lm83_data *data;
331b6aacdceSJean Delvare 
332*81de0eeaSGuenter Roeck 	data = devm_kzalloc(&client->dev, sizeof(struct lm83_data),
333c087f73aSGuenter Roeck 			    GFP_KERNEL);
334c087f73aSGuenter Roeck 	if (!data)
335c087f73aSGuenter Roeck 		return -ENOMEM;
336b6aacdceSJean Delvare 
337*81de0eeaSGuenter Roeck 	data->client = client;
3389a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
3398d5d45fbSJean Delvare 
3408d5d45fbSJean Delvare 	/*
3410e39e01cSJean Delvare 	 * Register sysfs hooks
34243cb7ebeSJordan Crouse 	 * The LM82 can only monitor one external diode which is
34343cb7ebeSJordan Crouse 	 * at the same register as the LM83 temp3 entry - so we
34443cb7ebeSJordan Crouse 	 * declare 1 and 3 common, and then 2 and 4 only for the LM83.
34543cb7ebeSJordan Crouse 	 */
346a0ac840dSGuenter Roeck 	data->groups[0] = &lm83_group;
347*81de0eeaSGuenter Roeck 	if (i2c_match_id(lm83_id, client)->driver_data == lm83)
348a0ac840dSGuenter Roeck 		data->groups[1] = &lm83_group_opt;
34943cb7ebeSJordan Crouse 
350*81de0eeaSGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
351*81de0eeaSGuenter Roeck 							   client->name,
352a0ac840dSGuenter Roeck 							   data, data->groups);
353a0ac840dSGuenter Roeck 	return PTR_ERR_OR_ZERO(hwmon_dev);
3548d5d45fbSJean Delvare }
3558d5d45fbSJean Delvare 
35641936370SGuenter Roeck /*
35741936370SGuenter Roeck  * Driver data (common to all clients)
35841936370SGuenter Roeck  */
3598d5d45fbSJean Delvare 
36041936370SGuenter Roeck static struct i2c_driver lm83_driver = {
36141936370SGuenter Roeck 	.class		= I2C_CLASS_HWMON,
36241936370SGuenter Roeck 	.driver = {
36341936370SGuenter Roeck 		.name	= "lm83",
36441936370SGuenter Roeck 	},
36567487038SStephen Kitt 	.probe_new	= lm83_probe,
36641936370SGuenter Roeck 	.id_table	= lm83_id,
36741936370SGuenter Roeck 	.detect		= lm83_detect,
36841936370SGuenter Roeck 	.address_list	= normal_i2c,
36941936370SGuenter Roeck };
3708d5d45fbSJean Delvare 
371f0967eeaSAxel Lin module_i2c_driver(lm83_driver);
3728d5d45fbSJean Delvare 
3737c81c60fSJean Delvare MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
3748d5d45fbSJean Delvare MODULE_DESCRIPTION("LM83 driver");
3758d5d45fbSJean Delvare MODULE_LICENSE("GPL");
376