xref: /openbmc/linux/drivers/hwmon/lm75.c (revision 90f4102c)
18d5d45fbSJean Delvare /*
2caaa0f36SShubhrajyoti D  * lm75.c - Part of lm_sensors, Linux kernel modules for hardware
3caaa0f36SShubhrajyoti D  *	 monitoring
4caaa0f36SShubhrajyoti D  * Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5caaa0f36SShubhrajyoti D  *
6caaa0f36SShubhrajyoti D  * This program is free software; you can redistribute it and/or modify
7caaa0f36SShubhrajyoti D  * it under the terms of the GNU General Public License as published by
8caaa0f36SShubhrajyoti D  * the Free Software Foundation; either version 2 of the License, or
9caaa0f36SShubhrajyoti D  * (at your option) any later version.
10caaa0f36SShubhrajyoti D  *
11caaa0f36SShubhrajyoti D  * This program is distributed in the hope that it will be useful,
12caaa0f36SShubhrajyoti D  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13caaa0f36SShubhrajyoti D  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14caaa0f36SShubhrajyoti D  * GNU General Public License for more details.
15caaa0f36SShubhrajyoti D  *
16caaa0f36SShubhrajyoti D  * You should have received a copy of the GNU General Public License
17caaa0f36SShubhrajyoti D  * along with this program; if not, write to the Free Software
18caaa0f36SShubhrajyoti D  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
198d5d45fbSJean Delvare  */
208d5d45fbSJean Delvare 
218d5d45fbSJean Delvare #include <linux/module.h>
228d5d45fbSJean Delvare #include <linux/init.h>
238d5d45fbSJean Delvare #include <linux/slab.h>
248d5d45fbSJean Delvare #include <linux/jiffies.h>
258d5d45fbSJean Delvare #include <linux/i2c.h>
26943b0830SMark M. Hoffman #include <linux/hwmon.h>
279ca8e40cSJean Delvare #include <linux/hwmon-sysfs.h>
28943b0830SMark M. Hoffman #include <linux/err.h>
299a61bf63SIngo Molnar #include <linux/mutex.h>
308d5d45fbSJean Delvare #include "lm75.h"
318d5d45fbSJean Delvare 
328d5d45fbSJean Delvare 
3301a52397SDavid Brownell /*
3401a52397SDavid Brownell  * This driver handles the LM75 and compatible digital temperature sensors.
3501a52397SDavid Brownell  */
3601a52397SDavid Brownell 
379ebd3d82SDavid Brownell enum lm75_type {		/* keep sorted in alphabetical order */
38e96f9d89SMichael Hennerich 	adt75,
391f86df49SJean Delvare 	ds1775,
409ebd3d82SDavid Brownell 	ds75,
411f86df49SJean Delvare 	lm75,
429ebd3d82SDavid Brownell 	lm75a,
439ebd3d82SDavid Brownell 	max6625,
449ebd3d82SDavid Brownell 	max6626,
459ebd3d82SDavid Brownell 	mcp980x,
469ebd3d82SDavid Brownell 	stds75,
479ebd3d82SDavid Brownell 	tcn75,
489ebd3d82SDavid Brownell 	tmp100,
499ebd3d82SDavid Brownell 	tmp101,
506d034059SShubhrajyoti Datta 	tmp105,
519ebd3d82SDavid Brownell 	tmp175,
529ebd3d82SDavid Brownell 	tmp275,
539ebd3d82SDavid Brownell 	tmp75,
549ebd3d82SDavid Brownell };
559ebd3d82SDavid Brownell 
568ff69eebSJean Delvare /* Addresses scanned */
5725e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
588d5d45fbSJean Delvare 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
598d5d45fbSJean Delvare 
608d5d45fbSJean Delvare 
618d5d45fbSJean Delvare /* The LM75 registers */
628d5d45fbSJean Delvare #define LM75_REG_CONF		0x01
639ca8e40cSJean Delvare static const u8 LM75_REG_TEMP[3] = {
649ca8e40cSJean Delvare 	0x00,		/* input */
659ca8e40cSJean Delvare 	0x03,		/* max */
669ca8e40cSJean Delvare 	0x02,		/* hyst */
679ca8e40cSJean Delvare };
688d5d45fbSJean Delvare 
698d5d45fbSJean Delvare /* Each client has this additional data */
708d5d45fbSJean Delvare struct lm75_data {
711beeffe4STony Jones 	struct device		*hwmon_dev;
729a61bf63SIngo Molnar 	struct mutex		update_lock;
739ebd3d82SDavid Brownell 	u8			orig_conf;
7401a52397SDavid Brownell 	char			valid;		/* !=0 if registers are valid */
758d5d45fbSJean Delvare 	unsigned long		last_updated;	/* In jiffies */
769ca8e40cSJean Delvare 	u16			temp[3];	/* Register values,
779ca8e40cSJean Delvare 						   0 = input
789ca8e40cSJean Delvare 						   1 = max
799ca8e40cSJean Delvare 						   2 = hyst */
808d5d45fbSJean Delvare };
818d5d45fbSJean Delvare 
828d5d45fbSJean Delvare static int lm75_read_value(struct i2c_client *client, u8 reg);
838d5d45fbSJean Delvare static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
848d5d45fbSJean Delvare static struct lm75_data *lm75_update_device(struct device *dev);
858d5d45fbSJean Delvare 
868d5d45fbSJean Delvare 
8701a52397SDavid Brownell /*-----------------------------------------------------------------------*/
8801a52397SDavid Brownell 
8901a52397SDavid Brownell /* sysfs attributes for hwmon */
908d5d45fbSJean Delvare 
919ca8e40cSJean Delvare static ssize_t show_temp(struct device *dev, struct device_attribute *da,
929ca8e40cSJean Delvare 			 char *buf)
939ca8e40cSJean Delvare {
949ca8e40cSJean Delvare 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
959ca8e40cSJean Delvare 	struct lm75_data *data = lm75_update_device(dev);
969ca8e40cSJean Delvare 	return sprintf(buf, "%d\n",
979ca8e40cSJean Delvare 		       LM75_TEMP_FROM_REG(data->temp[attr->index]));
988d5d45fbSJean Delvare }
998d5d45fbSJean Delvare 
1009ca8e40cSJean Delvare static ssize_t set_temp(struct device *dev, struct device_attribute *da,
1019ca8e40cSJean Delvare 			const char *buf, size_t count)
1029ca8e40cSJean Delvare {
1039ca8e40cSJean Delvare 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
1049ca8e40cSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
1059ca8e40cSJean Delvare 	struct lm75_data *data = i2c_get_clientdata(client);
1069ca8e40cSJean Delvare 	int nr = attr->index;
107e3cd9528SShubhrajyoti D 	long temp;
108e3cd9528SShubhrajyoti D 	int error;
109e3cd9528SShubhrajyoti D 
110e3cd9528SShubhrajyoti D 	error = strict_strtol(buf, 10, &temp);
111e3cd9528SShubhrajyoti D 	if (error)
112e3cd9528SShubhrajyoti D 		return error;
1139ca8e40cSJean Delvare 
1149ca8e40cSJean Delvare 	mutex_lock(&data->update_lock);
1159ca8e40cSJean Delvare 	data->temp[nr] = LM75_TEMP_TO_REG(temp);
1169ca8e40cSJean Delvare 	lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]);
1179ca8e40cSJean Delvare 	mutex_unlock(&data->update_lock);
1189ca8e40cSJean Delvare 	return count;
1198d5d45fbSJean Delvare }
1208d5d45fbSJean Delvare 
1219ca8e40cSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
1229ca8e40cSJean Delvare 			show_temp, set_temp, 1);
1239ca8e40cSJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
1249ca8e40cSJean Delvare 			show_temp, set_temp, 2);
1259ca8e40cSJean Delvare static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
1268d5d45fbSJean Delvare 
127c1685f61SMark M. Hoffman static struct attribute *lm75_attributes[] = {
1289ca8e40cSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
1299ca8e40cSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
1309ca8e40cSJean Delvare 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
131c1685f61SMark M. Hoffman 
132c1685f61SMark M. Hoffman 	NULL
133c1685f61SMark M. Hoffman };
134c1685f61SMark M. Hoffman 
135c1685f61SMark M. Hoffman static const struct attribute_group lm75_group = {
136c1685f61SMark M. Hoffman 	.attrs = lm75_attributes,
137c1685f61SMark M. Hoffman };
138c1685f61SMark M. Hoffman 
13901a52397SDavid Brownell /*-----------------------------------------------------------------------*/
14001a52397SDavid Brownell 
1418ff69eebSJean Delvare /* device probe and removal */
1429ebd3d82SDavid Brownell 
1439ebd3d82SDavid Brownell static int
1449ebd3d82SDavid Brownell lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
1459ebd3d82SDavid Brownell {
1469ebd3d82SDavid Brownell 	struct lm75_data *data;
1479ebd3d82SDavid Brownell 	int status;
1489ebd3d82SDavid Brownell 	u8 set_mask, clr_mask;
1499ebd3d82SDavid Brownell 	int new;
1509ebd3d82SDavid Brownell 
1519ebd3d82SDavid Brownell 	if (!i2c_check_functionality(client->adapter,
1529ebd3d82SDavid Brownell 			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
1539ebd3d82SDavid Brownell 		return -EIO;
1549ebd3d82SDavid Brownell 
1559ebd3d82SDavid Brownell 	data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL);
1569ebd3d82SDavid Brownell 	if (!data)
1579ebd3d82SDavid Brownell 		return -ENOMEM;
1589ebd3d82SDavid Brownell 
1599ebd3d82SDavid Brownell 	i2c_set_clientdata(client, data);
1609ebd3d82SDavid Brownell 	mutex_init(&data->update_lock);
1619ebd3d82SDavid Brownell 
1629ebd3d82SDavid Brownell 	/* Set to LM75 resolution (9 bits, 1/2 degree C) and range.
1639ebd3d82SDavid Brownell 	 * Then tweak to be more precise when appropriate.
1649ebd3d82SDavid Brownell 	 */
1659ebd3d82SDavid Brownell 	set_mask = 0;
1669ebd3d82SDavid Brownell 	clr_mask = (1 << 0)			/* continuous conversions */
1679ebd3d82SDavid Brownell 		| (1 << 6) | (1 << 5);		/* 9-bit mode */
1689ebd3d82SDavid Brownell 
1699ebd3d82SDavid Brownell 	/* configure as specified */
1709ebd3d82SDavid Brownell 	status = lm75_read_value(client, LM75_REG_CONF);
1719ebd3d82SDavid Brownell 	if (status < 0) {
1729ebd3d82SDavid Brownell 		dev_dbg(&client->dev, "Can't read config? %d\n", status);
1739ebd3d82SDavid Brownell 		goto exit_free;
1749ebd3d82SDavid Brownell 	}
1759ebd3d82SDavid Brownell 	data->orig_conf = status;
1769ebd3d82SDavid Brownell 	new = status & ~clr_mask;
1779ebd3d82SDavid Brownell 	new |= set_mask;
1789ebd3d82SDavid Brownell 	if (status != new)
1799ebd3d82SDavid Brownell 		lm75_write_value(client, LM75_REG_CONF, new);
1809ebd3d82SDavid Brownell 	dev_dbg(&client->dev, "Config %02x\n", new);
1819ebd3d82SDavid Brownell 
1829ebd3d82SDavid Brownell 	/* Register sysfs hooks */
1839ebd3d82SDavid Brownell 	status = sysfs_create_group(&client->dev.kobj, &lm75_group);
1849ebd3d82SDavid Brownell 	if (status)
1859ebd3d82SDavid Brownell 		goto exit_free;
1869ebd3d82SDavid Brownell 
1879ebd3d82SDavid Brownell 	data->hwmon_dev = hwmon_device_register(&client->dev);
1889ebd3d82SDavid Brownell 	if (IS_ERR(data->hwmon_dev)) {
1899ebd3d82SDavid Brownell 		status = PTR_ERR(data->hwmon_dev);
1909ebd3d82SDavid Brownell 		goto exit_remove;
1919ebd3d82SDavid Brownell 	}
1929ebd3d82SDavid Brownell 
1939ebd3d82SDavid Brownell 	dev_info(&client->dev, "%s: sensor '%s'\n",
194739cf3a2SKay Sievers 		 dev_name(data->hwmon_dev), client->name);
1959ebd3d82SDavid Brownell 
1969ebd3d82SDavid Brownell 	return 0;
1979ebd3d82SDavid Brownell 
1989ebd3d82SDavid Brownell exit_remove:
1999ebd3d82SDavid Brownell 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
2009ebd3d82SDavid Brownell exit_free:
2019ebd3d82SDavid Brownell 	kfree(data);
2029ebd3d82SDavid Brownell 	return status;
2039ebd3d82SDavid Brownell }
2049ebd3d82SDavid Brownell 
2059ebd3d82SDavid Brownell static int lm75_remove(struct i2c_client *client)
2069ebd3d82SDavid Brownell {
2079ebd3d82SDavid Brownell 	struct lm75_data *data = i2c_get_clientdata(client);
2089ebd3d82SDavid Brownell 
2099ebd3d82SDavid Brownell 	hwmon_device_unregister(data->hwmon_dev);
2109ebd3d82SDavid Brownell 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
2119ebd3d82SDavid Brownell 	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
2129ebd3d82SDavid Brownell 	kfree(data);
2139ebd3d82SDavid Brownell 	return 0;
2149ebd3d82SDavid Brownell }
2159ebd3d82SDavid Brownell 
2169ebd3d82SDavid Brownell static const struct i2c_device_id lm75_ids[] = {
217e96f9d89SMichael Hennerich 	{ "adt75", adt75, },
2189ebd3d82SDavid Brownell 	{ "ds1775", ds1775, },
2199ebd3d82SDavid Brownell 	{ "ds75", ds75, },
2209ebd3d82SDavid Brownell 	{ "lm75", lm75, },
2219ebd3d82SDavid Brownell 	{ "lm75a", lm75a, },
2229ebd3d82SDavid Brownell 	{ "max6625", max6625, },
2239ebd3d82SDavid Brownell 	{ "max6626", max6626, },
2249ebd3d82SDavid Brownell 	{ "mcp980x", mcp980x, },
2259ebd3d82SDavid Brownell 	{ "stds75", stds75, },
2269ebd3d82SDavid Brownell 	{ "tcn75", tcn75, },
2279ebd3d82SDavid Brownell 	{ "tmp100", tmp100, },
2289ebd3d82SDavid Brownell 	{ "tmp101", tmp101, },
2296d034059SShubhrajyoti Datta 	{ "tmp105", tmp105, },
2309ebd3d82SDavid Brownell 	{ "tmp175", tmp175, },
2319ebd3d82SDavid Brownell 	{ "tmp275", tmp275, },
2329ebd3d82SDavid Brownell 	{ "tmp75", tmp75, },
2339ebd3d82SDavid Brownell 	{ /* LIST END */ }
2349ebd3d82SDavid Brownell };
2359ebd3d82SDavid Brownell MODULE_DEVICE_TABLE(i2c, lm75_ids);
2369ebd3d82SDavid Brownell 
23705e82fe4SLen Sorensen #define LM75A_ID 0xA1
23805e82fe4SLen Sorensen 
2398ff69eebSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
240310ec792SJean Delvare static int lm75_detect(struct i2c_client *new_client,
2418ff69eebSJean Delvare 		       struct i2c_board_info *info)
2428d5d45fbSJean Delvare {
2438ff69eebSJean Delvare 	struct i2c_adapter *adapter = new_client->adapter;
2448d5d45fbSJean Delvare 	int i;
245e76f67b5SJean Delvare 	int conf, hyst, os;
24605e82fe4SLen Sorensen 	bool is_lm75a = 0;
2478d5d45fbSJean Delvare 
2488d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
2498d5d45fbSJean Delvare 				     I2C_FUNC_SMBUS_WORD_DATA))
2508ff69eebSJean Delvare 		return -ENODEV;
2518d5d45fbSJean Delvare 
252426343efSJean Delvare 	/*
253426343efSJean Delvare 	 * Now, we do the remaining detection. There is no identification-
254426343efSJean Delvare 	 * dedicated register so we have to rely on several tricks:
255426343efSJean Delvare 	 * unused bits, registers cycling over 8-address boundaries,
256426343efSJean Delvare 	 * addresses 0x04-0x07 returning the last read value.
257426343efSJean Delvare 	 * The cycling+unused addresses combination is not tested,
258426343efSJean Delvare 	 * since it would significantly slow the detection down and would
259426343efSJean Delvare 	 * hardly add any value.
260426343efSJean Delvare 	 *
261426343efSJean Delvare 	 * The National Semiconductor LM75A is different than earlier
262426343efSJean Delvare 	 * LM75s.  It has an ID byte of 0xaX (where X is the chip
263426343efSJean Delvare 	 * revision, with 1 being the only revision in existence) in
264426343efSJean Delvare 	 * register 7, and unused registers return 0xff rather than the
265426343efSJean Delvare 	 * last read value.
266426343efSJean Delvare 	 *
267426343efSJean Delvare 	 * Note that this function only detects the original National
268426343efSJean Delvare 	 * Semiconductor LM75 and the LM75A. Clones from other vendors
269426343efSJean Delvare 	 * aren't detected, on purpose, because they are typically never
270426343efSJean Delvare 	 * found on PC hardware. They are found on embedded designs where
271426343efSJean Delvare 	 * they can be instantiated explicitly so detection is not needed.
272426343efSJean Delvare 	 * The absence of identification registers on all these clones
273426343efSJean Delvare 	 * would make their exhaustive detection very difficult and weak,
274426343efSJean Delvare 	 * and odds are that the driver would bind to unsupported devices.
275426343efSJean Delvare 	 */
27605e82fe4SLen Sorensen 
277e76f67b5SJean Delvare 	/* Unused bits */
2788d5d45fbSJean Delvare 	conf = i2c_smbus_read_byte_data(new_client, 1);
279e76f67b5SJean Delvare 	if (conf & 0xe0)
280e76f67b5SJean Delvare 		return -ENODEV;
28105e82fe4SLen Sorensen 
28205e82fe4SLen Sorensen 	/* First check for LM75A */
28305e82fe4SLen Sorensen 	if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
28405e82fe4SLen Sorensen 		/* LM75A returns 0xff on unused registers so
28505e82fe4SLen Sorensen 		   just to be sure we check for that too. */
28605e82fe4SLen Sorensen 		if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
28705e82fe4SLen Sorensen 		 || i2c_smbus_read_byte_data(new_client, 5) != 0xff
28805e82fe4SLen Sorensen 		 || i2c_smbus_read_byte_data(new_client, 6) != 0xff)
28905e82fe4SLen Sorensen 			return -ENODEV;
29005e82fe4SLen Sorensen 		is_lm75a = 1;
291e76f67b5SJean Delvare 		hyst = i2c_smbus_read_byte_data(new_client, 2);
292e76f67b5SJean Delvare 		os = i2c_smbus_read_byte_data(new_client, 3);
29305e82fe4SLen Sorensen 	} else { /* Traditional style LM75 detection */
29405e82fe4SLen Sorensen 		/* Unused addresses */
295e76f67b5SJean Delvare 		hyst = i2c_smbus_read_byte_data(new_client, 2);
296e76f67b5SJean Delvare 		if (i2c_smbus_read_byte_data(new_client, 4) != hyst
297e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 5) != hyst
298e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 6) != hyst
299e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 7) != hyst)
3008ff69eebSJean Delvare 			return -ENODEV;
301e76f67b5SJean Delvare 		os = i2c_smbus_read_byte_data(new_client, 3);
302e76f67b5SJean Delvare 		if (i2c_smbus_read_byte_data(new_client, 4) != os
303e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 5) != os
304e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 6) != os
305e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, 7) != os)
3068ff69eebSJean Delvare 			return -ENODEV;
30705e82fe4SLen Sorensen 	}
3088d5d45fbSJean Delvare 
3098d5d45fbSJean Delvare 	/* Addresses cycling */
310e76f67b5SJean Delvare 	for (i = 8; i <= 248; i += 40) {
3118d5d45fbSJean Delvare 		if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
312e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, i + 2) != hyst
313e76f67b5SJean Delvare 		 || i2c_smbus_read_byte_data(new_client, i + 3) != os)
3148ff69eebSJean Delvare 			return -ENODEV;
31505e82fe4SLen Sorensen 		if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7)
31605e82fe4SLen Sorensen 				!= LM75A_ID)
31705e82fe4SLen Sorensen 			return -ENODEV;
3188d5d45fbSJean Delvare 	}
3198d5d45fbSJean Delvare 
32005e82fe4SLen Sorensen 	strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE);
3218d5d45fbSJean Delvare 
3228d5d45fbSJean Delvare 	return 0;
3238d5d45fbSJean Delvare }
3248d5d45fbSJean Delvare 
3259914518eSShubhrajyoti Datta #ifdef CONFIG_PM
3269914518eSShubhrajyoti Datta static int lm75_suspend(struct device *dev)
3279914518eSShubhrajyoti Datta {
3289914518eSShubhrajyoti Datta 	int status;
3299914518eSShubhrajyoti Datta 	struct i2c_client *client = to_i2c_client(dev);
3309914518eSShubhrajyoti Datta 	status = lm75_read_value(client, LM75_REG_CONF);
3319914518eSShubhrajyoti Datta 	if (status < 0) {
3329914518eSShubhrajyoti Datta 		dev_dbg(&client->dev, "Can't read config? %d\n", status);
3339914518eSShubhrajyoti Datta 		return status;
3349914518eSShubhrajyoti Datta 	}
3359914518eSShubhrajyoti Datta 	status = status | LM75_SHUTDOWN;
3369914518eSShubhrajyoti Datta 	lm75_write_value(client, LM75_REG_CONF, status);
3379914518eSShubhrajyoti Datta 	return 0;
3389914518eSShubhrajyoti Datta }
3399914518eSShubhrajyoti Datta 
3409914518eSShubhrajyoti Datta static int lm75_resume(struct device *dev)
3419914518eSShubhrajyoti Datta {
3429914518eSShubhrajyoti Datta 	int status;
3439914518eSShubhrajyoti Datta 	struct i2c_client *client = to_i2c_client(dev);
3449914518eSShubhrajyoti Datta 	status = lm75_read_value(client, LM75_REG_CONF);
3459914518eSShubhrajyoti Datta 	if (status < 0) {
3469914518eSShubhrajyoti Datta 		dev_dbg(&client->dev, "Can't read config? %d\n", status);
3479914518eSShubhrajyoti Datta 		return status;
3489914518eSShubhrajyoti Datta 	}
3499914518eSShubhrajyoti Datta 	status = status & ~LM75_SHUTDOWN;
3509914518eSShubhrajyoti Datta 	lm75_write_value(client, LM75_REG_CONF, status);
3519914518eSShubhrajyoti Datta 	return 0;
3529914518eSShubhrajyoti Datta }
3539914518eSShubhrajyoti Datta 
3549914518eSShubhrajyoti Datta static const struct dev_pm_ops lm75_dev_pm_ops = {
3559914518eSShubhrajyoti Datta 	.suspend	= lm75_suspend,
3569914518eSShubhrajyoti Datta 	.resume		= lm75_resume,
3579914518eSShubhrajyoti Datta };
3589914518eSShubhrajyoti Datta #define LM75_DEV_PM_OPS (&lm75_dev_pm_ops)
3599914518eSShubhrajyoti Datta #else
3609914518eSShubhrajyoti Datta #define LM75_DEV_PM_OPS NULL
3619914518eSShubhrajyoti Datta #endif /* CONFIG_PM */
3629914518eSShubhrajyoti Datta 
3638ff69eebSJean Delvare static struct i2c_driver lm75_driver = {
3648ff69eebSJean Delvare 	.class		= I2C_CLASS_HWMON,
36501a52397SDavid Brownell 	.driver = {
3668ff69eebSJean Delvare 		.name	= "lm75",
3679914518eSShubhrajyoti Datta 		.pm	= LM75_DEV_PM_OPS,
36801a52397SDavid Brownell 	},
3698ff69eebSJean Delvare 	.probe		= lm75_probe,
3708ff69eebSJean Delvare 	.remove		= lm75_remove,
3718ff69eebSJean Delvare 	.id_table	= lm75_ids,
3728ff69eebSJean Delvare 	.detect		= lm75_detect,
373c3813d6aSJean Delvare 	.address_list	= normal_i2c,
37401a52397SDavid Brownell };
37501a52397SDavid Brownell 
37601a52397SDavid Brownell /*-----------------------------------------------------------------------*/
37701a52397SDavid Brownell 
37801a52397SDavid Brownell /* register access */
37901a52397SDavid Brownell 
380caaa0f36SShubhrajyoti D /*
381caaa0f36SShubhrajyoti D  * All registers are word-sized, except for the configuration register.
382caaa0f36SShubhrajyoti D  * LM75 uses a high-byte first convention, which is exactly opposite to
383caaa0f36SShubhrajyoti D  * the SMBus standard.
384caaa0f36SShubhrajyoti D  */
3858d5d45fbSJean Delvare static int lm75_read_value(struct i2c_client *client, u8 reg)
3868d5d45fbSJean Delvare {
3878d5d45fbSJean Delvare 	if (reg == LM75_REG_CONF)
3888d5d45fbSJean Delvare 		return i2c_smbus_read_byte_data(client, reg);
38990f4102cSJean Delvare 	else
39090f4102cSJean Delvare 		return i2c_smbus_read_word_swapped(client, reg);
3918d5d45fbSJean Delvare }
3928d5d45fbSJean Delvare 
3938d5d45fbSJean Delvare static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
3948d5d45fbSJean Delvare {
3958d5d45fbSJean Delvare 	if (reg == LM75_REG_CONF)
3968d5d45fbSJean Delvare 		return i2c_smbus_write_byte_data(client, reg, value);
3978d5d45fbSJean Delvare 	else
39890f4102cSJean Delvare 		return i2c_smbus_write_word_swapped(client, reg, value);
3998d5d45fbSJean Delvare }
4008d5d45fbSJean Delvare 
4018d5d45fbSJean Delvare static struct lm75_data *lm75_update_device(struct device *dev)
4028d5d45fbSJean Delvare {
4038d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4048d5d45fbSJean Delvare 	struct lm75_data *data = i2c_get_clientdata(client);
4058d5d45fbSJean Delvare 
4069a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4078d5d45fbSJean Delvare 
4088d5d45fbSJean Delvare 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
4098d5d45fbSJean Delvare 	    || !data->valid) {
4109ca8e40cSJean Delvare 		int i;
4118d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting lm75 update\n");
4128d5d45fbSJean Delvare 
413bcccc3a2SDavid Brownell 		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
414bcccc3a2SDavid Brownell 			int status;
415bcccc3a2SDavid Brownell 
416bcccc3a2SDavid Brownell 			status = lm75_read_value(client, LM75_REG_TEMP[i]);
417bcccc3a2SDavid Brownell 			if (status < 0)
418bcccc3a2SDavid Brownell 				dev_dbg(&client->dev, "reg %d, err %d\n",
419bcccc3a2SDavid Brownell 						LM75_REG_TEMP[i], status);
420bcccc3a2SDavid Brownell 			else
421bcccc3a2SDavid Brownell 				data->temp[i] = status;
422bcccc3a2SDavid Brownell 		}
4238d5d45fbSJean Delvare 		data->last_updated = jiffies;
4248d5d45fbSJean Delvare 		data->valid = 1;
4258d5d45fbSJean Delvare 	}
4268d5d45fbSJean Delvare 
4279a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4288d5d45fbSJean Delvare 
4298d5d45fbSJean Delvare 	return data;
4308d5d45fbSJean Delvare }
4318d5d45fbSJean Delvare 
43201a52397SDavid Brownell /*-----------------------------------------------------------------------*/
43301a52397SDavid Brownell 
43401a52397SDavid Brownell /* module glue */
43501a52397SDavid Brownell 
4368d5d45fbSJean Delvare static int __init sensors_lm75_init(void)
4378d5d45fbSJean Delvare {
4388ff69eebSJean Delvare 	return i2c_add_driver(&lm75_driver);
4398d5d45fbSJean Delvare }
4408d5d45fbSJean Delvare 
4418d5d45fbSJean Delvare static void __exit sensors_lm75_exit(void)
4428d5d45fbSJean Delvare {
4438d5d45fbSJean Delvare 	i2c_del_driver(&lm75_driver);
4448d5d45fbSJean Delvare }
4458d5d45fbSJean Delvare 
4468d5d45fbSJean Delvare MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
4478d5d45fbSJean Delvare MODULE_DESCRIPTION("LM75 driver");
4488d5d45fbSJean Delvare MODULE_LICENSE("GPL");
4498d5d45fbSJean Delvare 
4508d5d45fbSJean Delvare module_init(sensors_lm75_init);
4518d5d45fbSJean Delvare module_exit(sensors_lm75_exit);
452