xref: /linux/drivers/hwmon/tmp102.c (revision beb1b6bbf2b448b97b9611200eb4b5a555336c60)
1*beb1b6bbSSteven King /* Texas Instruments TMP102 SMBUS temperature sensor driver
2*beb1b6bbSSteven King  *
3*beb1b6bbSSteven King  * Copyright 2010 Steven King <sfking@fdwdc.com>
4*beb1b6bbSSteven King  *
5*beb1b6bbSSteven King  * This program is free software; you can redistribute it and/or modify
6*beb1b6bbSSteven King  * it under the terms of the GNU General Public License as published by
7*beb1b6bbSSteven King  * the Free Software Foundation; either version 2 of the License, or
8*beb1b6bbSSteven King  * (at your option) any later version.
9*beb1b6bbSSteven King  *
10*beb1b6bbSSteven King  * This program is distributed in the hope that it will be useful,
11*beb1b6bbSSteven King  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*beb1b6bbSSteven King  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*beb1b6bbSSteven King  * GNU General Public License for more details.
14*beb1b6bbSSteven King  *
15*beb1b6bbSSteven King  * You should have received a copy of the GNU General Public License
16*beb1b6bbSSteven King  * along with this program; if not, write to the Free Software
17*beb1b6bbSSteven King  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
18*beb1b6bbSSteven King  */
19*beb1b6bbSSteven King 
20*beb1b6bbSSteven King 
21*beb1b6bbSSteven King 
22*beb1b6bbSSteven King #include <linux/module.h>
23*beb1b6bbSSteven King #include <linux/init.h>
24*beb1b6bbSSteven King #include <linux/slab.h>
25*beb1b6bbSSteven King #include <linux/i2c.h>
26*beb1b6bbSSteven King #include <linux/hwmon.h>
27*beb1b6bbSSteven King #include <linux/hwmon-sysfs.h>
28*beb1b6bbSSteven King #include <linux/err.h>
29*beb1b6bbSSteven King #include <linux/mutex.h>
30*beb1b6bbSSteven King #include <linux/delay.h>
31*beb1b6bbSSteven King 
32*beb1b6bbSSteven King #define	DRIVER_NAME "tmp102"
33*beb1b6bbSSteven King 
34*beb1b6bbSSteven King #define	TMP102_TEMP_REG			0x00
35*beb1b6bbSSteven King #define	TMP102_CONF_REG			0x01
36*beb1b6bbSSteven King /* note: these bit definitions are byte swapped */
37*beb1b6bbSSteven King #define		TMP102_CONF_SD		0x0100
38*beb1b6bbSSteven King #define		TMP102_CONF_TM		0x0200
39*beb1b6bbSSteven King #define		TMP102_CONF_POL		0x0400
40*beb1b6bbSSteven King #define		TMP102_CONF_F0		0x0800
41*beb1b6bbSSteven King #define		TMP102_CONF_F1		0x1000
42*beb1b6bbSSteven King #define		TMP102_CONF_R0		0x2000
43*beb1b6bbSSteven King #define		TMP102_CONF_R1		0x4000
44*beb1b6bbSSteven King #define		TMP102_CONF_OS		0x8000
45*beb1b6bbSSteven King #define		TMP102_CONF_EM		0x0010
46*beb1b6bbSSteven King #define		TMP102_CONF_AL		0x0020
47*beb1b6bbSSteven King #define		TMP102_CONF_CR0		0x0040
48*beb1b6bbSSteven King #define		TMP102_CONF_CR1		0x0080
49*beb1b6bbSSteven King #define	TMP102_TLOW_REG			0x02
50*beb1b6bbSSteven King #define	TMP102_THIGH_REG		0x03
51*beb1b6bbSSteven King 
52*beb1b6bbSSteven King struct tmp102 {
53*beb1b6bbSSteven King 	struct device *hwmon_dev;
54*beb1b6bbSSteven King 	struct mutex lock;
55*beb1b6bbSSteven King 	unsigned long last_update;
56*beb1b6bbSSteven King 	int temp[3];
57*beb1b6bbSSteven King };
58*beb1b6bbSSteven King 
59*beb1b6bbSSteven King /* the TMP102 registers are big endian so we have to swab16 the values */
60*beb1b6bbSSteven King static int tmp102_read_reg(struct i2c_client *client, u8 reg)
61*beb1b6bbSSteven King {
62*beb1b6bbSSteven King 	int result = i2c_smbus_read_word_data(client, reg);
63*beb1b6bbSSteven King 	return result < 0 ? result : swab16(result);
64*beb1b6bbSSteven King }
65*beb1b6bbSSteven King 
66*beb1b6bbSSteven King static int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
67*beb1b6bbSSteven King {
68*beb1b6bbSSteven King 	return i2c_smbus_write_word_data(client, reg, swab16(val));
69*beb1b6bbSSteven King }
70*beb1b6bbSSteven King 
71*beb1b6bbSSteven King /* convert left adjusted 13bit TMP102 register value to miliCelsius */
72*beb1b6bbSSteven King static int tmp102_reg_to_mC(s16 val)
73*beb1b6bbSSteven King {
74*beb1b6bbSSteven King 	return (val * 1000) / 128;
75*beb1b6bbSSteven King }
76*beb1b6bbSSteven King 
77*beb1b6bbSSteven King /* convert miliCelsius to left adjusted 13bit TMP102 register value */
78*beb1b6bbSSteven King static u16 tmp102_mC_to_reg(int val)
79*beb1b6bbSSteven King {
80*beb1b6bbSSteven King 	return (val * 128) / 1000;
81*beb1b6bbSSteven King }
82*beb1b6bbSSteven King 
83*beb1b6bbSSteven King static const u8 tmp102_reg[] = {
84*beb1b6bbSSteven King 	TMP102_TEMP_REG,
85*beb1b6bbSSteven King 	TMP102_TLOW_REG,
86*beb1b6bbSSteven King 	TMP102_THIGH_REG,
87*beb1b6bbSSteven King };
88*beb1b6bbSSteven King 
89*beb1b6bbSSteven King static struct tmp102 *tmp102_update_device(struct i2c_client *client)
90*beb1b6bbSSteven King {
91*beb1b6bbSSteven King 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
92*beb1b6bbSSteven King 
93*beb1b6bbSSteven King 	mutex_lock(&tmp102->lock);
94*beb1b6bbSSteven King 	if (time_after(jiffies, tmp102->last_update + HZ / 4)) {
95*beb1b6bbSSteven King 		int i;
96*beb1b6bbSSteven King 		for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
97*beb1b6bbSSteven King 			int status = tmp102_read_reg(client, tmp102_reg[i]);
98*beb1b6bbSSteven King 			if (status > -1)
99*beb1b6bbSSteven King 				tmp102->temp[i] = tmp102_reg_to_mC(status);
100*beb1b6bbSSteven King 		}
101*beb1b6bbSSteven King 		tmp102->last_update = jiffies;
102*beb1b6bbSSteven King 	}
103*beb1b6bbSSteven King 	mutex_unlock(&tmp102->lock);
104*beb1b6bbSSteven King 	return tmp102;
105*beb1b6bbSSteven King }
106*beb1b6bbSSteven King 
107*beb1b6bbSSteven King static ssize_t tmp102_show_temp(struct device *dev,
108*beb1b6bbSSteven King 				struct device_attribute *attr,
109*beb1b6bbSSteven King 				char *buf)
110*beb1b6bbSSteven King {
111*beb1b6bbSSteven King 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
112*beb1b6bbSSteven King 	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
113*beb1b6bbSSteven King 
114*beb1b6bbSSteven King 	return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
115*beb1b6bbSSteven King }
116*beb1b6bbSSteven King 
117*beb1b6bbSSteven King static ssize_t tmp102_set_temp(struct device *dev,
118*beb1b6bbSSteven King 			       struct device_attribute *attr,
119*beb1b6bbSSteven King 			       const char *buf, size_t count)
120*beb1b6bbSSteven King {
121*beb1b6bbSSteven King 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
122*beb1b6bbSSteven King 	struct i2c_client *client = to_i2c_client(dev);
123*beb1b6bbSSteven King 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
124*beb1b6bbSSteven King 	long val;
125*beb1b6bbSSteven King 	int status = 0;
126*beb1b6bbSSteven King 
127*beb1b6bbSSteven King 	if ((strict_strtol(buf, 10, &val) < 0) || (abs(val) > 150000))
128*beb1b6bbSSteven King 		return -EINVAL;
129*beb1b6bbSSteven King 	mutex_lock(&tmp102->lock);
130*beb1b6bbSSteven King 	if (tmp102->temp[sda->index] != val) {
131*beb1b6bbSSteven King 		tmp102->temp[sda->index] = val;
132*beb1b6bbSSteven King 		status = tmp102_write_reg(client, tmp102_reg[sda->index],
133*beb1b6bbSSteven King 					  tmp102_mC_to_reg(val));
134*beb1b6bbSSteven King 	}
135*beb1b6bbSSteven King 	mutex_unlock(&tmp102->lock);
136*beb1b6bbSSteven King 	return status ? : count;
137*beb1b6bbSSteven King }
138*beb1b6bbSSteven King 
139*beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0);
140*beb1b6bbSSteven King 
141*beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
142*beb1b6bbSSteven King 			  tmp102_set_temp, 1);
143*beb1b6bbSSteven King 
144*beb1b6bbSSteven King static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
145*beb1b6bbSSteven King 			  tmp102_set_temp, 2);
146*beb1b6bbSSteven King 
147*beb1b6bbSSteven King static struct attribute *tmp102_attributes[] = {
148*beb1b6bbSSteven King 	&sensor_dev_attr_temp1_input.dev_attr.attr,
149*beb1b6bbSSteven King 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
150*beb1b6bbSSteven King 	&sensor_dev_attr_temp1_max.dev_attr.attr,
151*beb1b6bbSSteven King 	NULL
152*beb1b6bbSSteven King };
153*beb1b6bbSSteven King 
154*beb1b6bbSSteven King static const struct attribute_group tmp102_attr_group = {
155*beb1b6bbSSteven King 	.attrs = tmp102_attributes,
156*beb1b6bbSSteven King };
157*beb1b6bbSSteven King 
158*beb1b6bbSSteven King #define TMP102_CONFIG  (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
159*beb1b6bbSSteven King #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
160*beb1b6bbSSteven King 
161*beb1b6bbSSteven King static int __devinit tmp102_probe(struct i2c_client *client,
162*beb1b6bbSSteven King 				  const struct i2c_device_id *id)
163*beb1b6bbSSteven King {
164*beb1b6bbSSteven King 	struct tmp102 *tmp102;
165*beb1b6bbSSteven King 	int status;
166*beb1b6bbSSteven King 
167*beb1b6bbSSteven King 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
168*beb1b6bbSSteven King 				     I2C_FUNC_SMBUS_WORD_DATA)) {
169*beb1b6bbSSteven King 		dev_dbg(&client->dev, "adapter doesnt support SMBUS\n");
170*beb1b6bbSSteven King 		return -ENODEV;
171*beb1b6bbSSteven King 	}
172*beb1b6bbSSteven King 
173*beb1b6bbSSteven King 	tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL);
174*beb1b6bbSSteven King 	if (!tmp102) {
175*beb1b6bbSSteven King 		dev_dbg(&client->dev, "kzalloc failed\n");
176*beb1b6bbSSteven King 		return -ENOMEM;
177*beb1b6bbSSteven King 	}
178*beb1b6bbSSteven King 	i2c_set_clientdata(client, tmp102);
179*beb1b6bbSSteven King 
180*beb1b6bbSSteven King 	tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
181*beb1b6bbSSteven King 	status = tmp102_read_reg(client, TMP102_CONF_REG);
182*beb1b6bbSSteven King 	if (status < 0) {
183*beb1b6bbSSteven King 		dev_dbg(&client->dev, "error reading config register\n");
184*beb1b6bbSSteven King 		goto fail0;
185*beb1b6bbSSteven King 	}
186*beb1b6bbSSteven King 	status &= ~TMP102_CONFIG_RD_ONLY;
187*beb1b6bbSSteven King 	if (status != TMP102_CONFIG) {
188*beb1b6bbSSteven King 		dev_dbg(&client->dev, "could not verify config settings\n");
189*beb1b6bbSSteven King 		status = -EIO;
190*beb1b6bbSSteven King 		goto fail0;
191*beb1b6bbSSteven King 	}
192*beb1b6bbSSteven King 	tmp102->last_update = jiffies - HZ;
193*beb1b6bbSSteven King 	mutex_init(&tmp102->lock);
194*beb1b6bbSSteven King 
195*beb1b6bbSSteven King 	status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group);
196*beb1b6bbSSteven King 	if (status) {
197*beb1b6bbSSteven King 		dev_dbg(&client->dev, "could not create sysfs files\n");
198*beb1b6bbSSteven King 		goto fail0;
199*beb1b6bbSSteven King 	}
200*beb1b6bbSSteven King 	tmp102->hwmon_dev = hwmon_device_register(&client->dev);
201*beb1b6bbSSteven King 	if (IS_ERR(tmp102->hwmon_dev)) {
202*beb1b6bbSSteven King 		dev_dbg(&client->dev, "unable to register hwmon device\n");
203*beb1b6bbSSteven King 		status = PTR_ERR(tmp102->hwmon_dev);
204*beb1b6bbSSteven King 		goto fail1;
205*beb1b6bbSSteven King 	}
206*beb1b6bbSSteven King 
207*beb1b6bbSSteven King 	dev_info(&client->dev, "initialized\n");
208*beb1b6bbSSteven King 
209*beb1b6bbSSteven King 	return 0;
210*beb1b6bbSSteven King fail1:
211*beb1b6bbSSteven King 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
212*beb1b6bbSSteven King fail0:
213*beb1b6bbSSteven King 	i2c_set_clientdata(client, NULL);
214*beb1b6bbSSteven King 	kfree(tmp102);
215*beb1b6bbSSteven King 
216*beb1b6bbSSteven King 	return 0;
217*beb1b6bbSSteven King }
218*beb1b6bbSSteven King 
219*beb1b6bbSSteven King static int __devexit tmp102_remove(struct i2c_client *client)
220*beb1b6bbSSteven King {
221*beb1b6bbSSteven King 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
222*beb1b6bbSSteven King 
223*beb1b6bbSSteven King 	/* shutdown the chip */
224*beb1b6bbSSteven King 	tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONF_SD);
225*beb1b6bbSSteven King 
226*beb1b6bbSSteven King 	hwmon_device_unregister(tmp102->hwmon_dev);
227*beb1b6bbSSteven King 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
228*beb1b6bbSSteven King 	i2c_set_clientdata(client, NULL);
229*beb1b6bbSSteven King 	kfree(tmp102);
230*beb1b6bbSSteven King 
231*beb1b6bbSSteven King 	return 0;
232*beb1b6bbSSteven King }
233*beb1b6bbSSteven King 
234*beb1b6bbSSteven King #ifdef CONFIG_PM
235*beb1b6bbSSteven King static int tmp102_suspend(struct device *dev)
236*beb1b6bbSSteven King {
237*beb1b6bbSSteven King 	struct i2c_client *client = to_i2c_client(dev);
238*beb1b6bbSSteven King 
239*beb1b6bbSSteven King 	tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONF_SD);
240*beb1b6bbSSteven King 
241*beb1b6bbSSteven King 	return 0;
242*beb1b6bbSSteven King }
243*beb1b6bbSSteven King 
244*beb1b6bbSSteven King static int tmp102_resume(struct device *dev)
245*beb1b6bbSSteven King {
246*beb1b6bbSSteven King 	struct i2c_client *client = to_i2c_client(dev);
247*beb1b6bbSSteven King 
248*beb1b6bbSSteven King 	tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
249*beb1b6bbSSteven King 
250*beb1b6bbSSteven King 	return 0;
251*beb1b6bbSSteven King }
252*beb1b6bbSSteven King 
253*beb1b6bbSSteven King static const struct dev_pm_ops tmp102_dev_pm_ops = {
254*beb1b6bbSSteven King 	.suspend	= tmp102_suspend,
255*beb1b6bbSSteven King 	.resume		= tmp102_resume,
256*beb1b6bbSSteven King };
257*beb1b6bbSSteven King 
258*beb1b6bbSSteven King #define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops)
259*beb1b6bbSSteven King #else
260*beb1b6bbSSteven King #define	TMP102_DEV_PM_OPS NULL
261*beb1b6bbSSteven King #endif /* CONFIG_PM */
262*beb1b6bbSSteven King 
263*beb1b6bbSSteven King static const unsigned short normal_i2c[] = {
264*beb1b6bbSSteven King 	0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END
265*beb1b6bbSSteven King };
266*beb1b6bbSSteven King 
267*beb1b6bbSSteven King static const struct i2c_device_id tmp102_id[] = {
268*beb1b6bbSSteven King 	{ DRIVER_NAME, 0 },
269*beb1b6bbSSteven King 	{ }
270*beb1b6bbSSteven King };
271*beb1b6bbSSteven King 
272*beb1b6bbSSteven King static struct i2c_driver tmp102_driver = {
273*beb1b6bbSSteven King 	.driver.name	= DRIVER_NAME,
274*beb1b6bbSSteven King 	.driver.pm	= TMP102_DEV_PM_OPS,
275*beb1b6bbSSteven King 	.class		= I2C_CLASS_HWMON,
276*beb1b6bbSSteven King 	.probe		= tmp102_probe,
277*beb1b6bbSSteven King 	.remove		= __devexit_p(tmp102_remove),
278*beb1b6bbSSteven King 	.id_table	= tmp102_id,
279*beb1b6bbSSteven King 	.address_list	= normal_i2c,
280*beb1b6bbSSteven King };
281*beb1b6bbSSteven King 
282*beb1b6bbSSteven King static int __init tmp102_init(void)
283*beb1b6bbSSteven King {
284*beb1b6bbSSteven King 	return i2c_add_driver(&tmp102_driver);
285*beb1b6bbSSteven King }
286*beb1b6bbSSteven King module_init(tmp102_init);
287*beb1b6bbSSteven King 
288*beb1b6bbSSteven King static void __exit tmp102_exit(void)
289*beb1b6bbSSteven King {
290*beb1b6bbSSteven King 	i2c_del_driver(&tmp102_driver);
291*beb1b6bbSSteven King }
292*beb1b6bbSSteven King module_exit(tmp102_exit);
293*beb1b6bbSSteven King 
294*beb1b6bbSSteven King 
295*beb1b6bbSSteven King MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
296*beb1b6bbSSteven King MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
297*beb1b6bbSSteven King MODULE_LICENSE("GPL");
298