Linux Audio

Check our new training course

Loading...
  1/*
  2 * smsc47m192.c - Support for hardware monitoring block of
  3 *		  SMSC LPC47M192 and compatible Super I/O chips
  4 *
  5 * Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
  6 *
  7 * Derived from lm78.c and other chip drivers.
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License as published by
 11 * the Free Software Foundation; either version 2 of the License, or
 12 * (at your option) any later version.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with this program; if not, write to the Free Software
 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 22 */
 23
 24#include <linux/module.h>
 25#include <linux/init.h>
 26#include <linux/slab.h>
 27#include <linux/jiffies.h>
 28#include <linux/i2c.h>
 29#include <linux/hwmon.h>
 30#include <linux/hwmon-sysfs.h>
 31#include <linux/hwmon-vid.h>
 32#include <linux/err.h>
 33#include <linux/sysfs.h>
 34#include <linux/mutex.h>
 35
 36/* Addresses to scan */
 37static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
 38
 39/* SMSC47M192 registers */
 40#define SMSC47M192_REG_IN(nr)		((nr) < 6 ? (0x20 + (nr)) : \
 41					(0x50 + (nr) - 6))
 42#define SMSC47M192_REG_IN_MAX(nr)	((nr) < 6 ? (0x2b + (nr) * 2) : \
 43					(0x54 + (((nr) - 6) * 2)))
 44#define SMSC47M192_REG_IN_MIN(nr)	((nr) < 6 ? (0x2c + (nr) * 2) : \
 45					(0x55 + (((nr) - 6) * 2)))
 46static u8 SMSC47M192_REG_TEMP[3] =	{ 0x27, 0x26, 0x52 };
 47static u8 SMSC47M192_REG_TEMP_MAX[3] =	{ 0x39, 0x37, 0x58 };
 48static u8 SMSC47M192_REG_TEMP_MIN[3] =	{ 0x3A, 0x38, 0x59 };
 49#define SMSC47M192_REG_TEMP_OFFSET(nr)	((nr) == 2 ? 0x1e : 0x1f)
 50#define SMSC47M192_REG_ALARM1		0x41
 51#define SMSC47M192_REG_ALARM2		0x42
 52#define SMSC47M192_REG_VID		0x47
 53#define SMSC47M192_REG_VID4		0x49
 54#define SMSC47M192_REG_CONFIG		0x40
 55#define SMSC47M192_REG_SFR		0x4f
 56#define SMSC47M192_REG_COMPANY_ID	0x3e
 57#define SMSC47M192_REG_VERSION		0x3f
 58
 59/* generalised scaling with integer rounding */
 60static inline int SCALE(long val, int mul, int div)
 61{
 62	if (val < 0)
 63		return (val * mul - div / 2) / div;
 64	else
 65		return (val * mul + div / 2) / div;
 66}
 67
 68/* Conversions */
 69
 70/* smsc47m192 internally scales voltage measurements */
 71static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 };
 72
 73static inline unsigned int IN_FROM_REG(u8 reg, int n)
 74{
 75	return SCALE(reg, nom_mv[n], 192);
 76}
 77
 78static inline u8 IN_TO_REG(unsigned long val, int n)
 79{
 80	return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
 81}
 82
 83/*
 84 * TEMP: 0.001 degC units (-128C to +127C)
 85 * REG: 1C/bit, two's complement
 86 */
 87static inline s8 TEMP_TO_REG(int val)
 88{
 89	return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000);
 90}
 91
 92static inline int TEMP_FROM_REG(s8 val)
 93{
 94	return val * 1000;
 95}
 96
 97struct smsc47m192_data {
 98	struct device *hwmon_dev;
 99	struct mutex update_lock;
100	char valid;		/* !=0 if following fields are valid */
101	unsigned long last_updated;	/* In jiffies */
102
103	u8 in[8];		/* Register value */
104	u8 in_max[8];		/* Register value */
105	u8 in_min[8];		/* Register value */
106	s8 temp[3];		/* Register value */
107	s8 temp_max[3];		/* Register value */
108	s8 temp_min[3];		/* Register value */
109	s8 temp_offset[3];	/* Register value */
110	u16 alarms;		/* Register encoding, combined */
111	u8 vid;			/* Register encoding, combined */
112	u8 vrm;
113};
114
115static int smsc47m192_probe(struct i2c_client *client,
116			    const struct i2c_device_id *id);
117static int smsc47m192_detect(struct i2c_client *client,
118			     struct i2c_board_info *info);
119static int smsc47m192_remove(struct i2c_client *client);
120static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
121
122static const struct i2c_device_id smsc47m192_id[] = {
123	{ "smsc47m192", 0 },
124	{ }
125};
126MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
127
128static struct i2c_driver smsc47m192_driver = {
129	.class		= I2C_CLASS_HWMON,
130	.driver = {
131		.name	= "smsc47m192",
132	},
133	.probe		= smsc47m192_probe,
134	.remove		= smsc47m192_remove,
135	.id_table	= smsc47m192_id,
136	.detect		= smsc47m192_detect,
137	.address_list	= normal_i2c,
138};
139
140/* Voltages */
141static ssize_t show_in(struct device *dev, struct device_attribute *attr,
142		char *buf)
143{
144	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
145	int nr = sensor_attr->index;
146	struct smsc47m192_data *data = smsc47m192_update_device(dev);
147	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
148}
149
150static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
151		char *buf)
152{
153	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
154	int nr = sensor_attr->index;
155	struct smsc47m192_data *data = smsc47m192_update_device(dev);
156	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
157}
158
159static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
160		char *buf)
161{
162	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
163	int nr = sensor_attr->index;
164	struct smsc47m192_data *data = smsc47m192_update_device(dev);
165	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
166}
167
168static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
169		const char *buf, size_t count)
170{
171	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
172	int nr = sensor_attr->index;
173	struct i2c_client *client = to_i2c_client(dev);
174	struct smsc47m192_data *data = i2c_get_clientdata(client);
175	unsigned long val;
176	int err;
177
178	err = kstrtoul(buf, 10, &val);
179	if (err)
180		return err;
181
182	mutex_lock(&data->update_lock);
183	data->in_min[nr] = IN_TO_REG(val, nr);
184	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr),
185							data->in_min[nr]);
186	mutex_unlock(&data->update_lock);
187	return count;
188}
189
190static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
191		const char *buf, size_t count)
192{
193	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
194	int nr = sensor_attr->index;
195	struct i2c_client *client = to_i2c_client(dev);
196	struct smsc47m192_data *data = i2c_get_clientdata(client);
197	unsigned long val;
198	int err;
199
200	err = kstrtoul(buf, 10, &val);
201	if (err)
202		return err;
203
204	mutex_lock(&data->update_lock);
205	data->in_max[nr] = IN_TO_REG(val, nr);
206	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr),
207							data->in_max[nr]);
208	mutex_unlock(&data->update_lock);
209	return count;
210}
211
212#define show_in_offset(offset)					\
213static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
214		show_in, NULL, offset);				\
215static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
216		show_in_min, set_in_min, offset);		\
217static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
218		show_in_max, set_in_max, offset);
219
220show_in_offset(0)
221show_in_offset(1)
222show_in_offset(2)
223show_in_offset(3)
224show_in_offset(4)
225show_in_offset(5)
226show_in_offset(6)
227show_in_offset(7)
228
229/* Temperatures */
230static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
231		char *buf)
232{
233	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
234	int nr = sensor_attr->index;
235	struct smsc47m192_data *data = smsc47m192_update_device(dev);
236	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
237}
238
239static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
240		char *buf)
241{
242	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
243	int nr = sensor_attr->index;
244	struct smsc47m192_data *data = smsc47m192_update_device(dev);
245	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
246}
247
248static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
249		char *buf)
250{
251	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
252	int nr = sensor_attr->index;
253	struct smsc47m192_data *data = smsc47m192_update_device(dev);
254	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
255}
256
257static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
258		const char *buf, size_t count)
259{
260	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
261	int nr = sensor_attr->index;
262	struct i2c_client *client = to_i2c_client(dev);
263	struct smsc47m192_data *data = i2c_get_clientdata(client);
264	long val;
265	int err;
266
267	err = kstrtol(buf, 10, &val);
268	if (err)
269		return err;
270
271	mutex_lock(&data->update_lock);
272	data->temp_min[nr] = TEMP_TO_REG(val);
273	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr],
274						data->temp_min[nr]);
275	mutex_unlock(&data->update_lock);
276	return count;
277}
278
279static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
280		const char *buf, size_t count)
281{
282	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
283	int nr = sensor_attr->index;
284	struct i2c_client *client = to_i2c_client(dev);
285	struct smsc47m192_data *data = i2c_get_clientdata(client);
286	long val;
287	int err;
288
289	err = kstrtol(buf, 10, &val);
290	if (err)
291		return err;
292
293	mutex_lock(&data->update_lock);
294	data->temp_max[nr] = TEMP_TO_REG(val);
295	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr],
296						data->temp_max[nr]);
297	mutex_unlock(&data->update_lock);
298	return count;
299}
300
301static ssize_t show_temp_offset(struct device *dev, struct device_attribute
302		*attr, char *buf)
303{
304	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
305	int nr = sensor_attr->index;
306	struct smsc47m192_data *data = smsc47m192_update_device(dev);
307	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
308}
309
310static ssize_t set_temp_offset(struct device *dev, struct device_attribute
311		*attr, const char *buf, size_t count)
312{
313	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
314	int nr = sensor_attr->index;
315	struct i2c_client *client = to_i2c_client(dev);
316	struct smsc47m192_data *data = i2c_get_clientdata(client);
317	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
318	long val;
319	int err;
320
321	err = kstrtol(buf, 10, &val);
322	if (err)
323		return err;
324
325	mutex_lock(&data->update_lock);
326	data->temp_offset[nr] = TEMP_TO_REG(val);
327	if (nr > 1)
328		i2c_smbus_write_byte_data(client,
329			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
330	else if (data->temp_offset[nr] != 0) {
331		/*
332		 * offset[0] and offset[1] share the same register,
333		 * SFR bit 4 activates offset[0]
334		 */
335		i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
336					(sfr & 0xef) | (nr == 0 ? 0x10 : 0));
337		data->temp_offset[1-nr] = 0;
338		i2c_smbus_write_byte_data(client,
339			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
340	} else if ((sfr & 0x10) == (nr == 0 ? 0x10 : 0))
341		i2c_smbus_write_byte_data(client,
342					SMSC47M192_REG_TEMP_OFFSET(nr), 0);
343	mutex_unlock(&data->update_lock);
344	return count;
345}
346
347#define show_temp_index(index)						\
348static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO,			\
349		show_temp, NULL, index-1);				\
350static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR,		\
351		show_temp_min, set_temp_min, index-1);			\
352static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR,		\
353		show_temp_max, set_temp_max, index-1);			\
354static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR,	\
355		show_temp_offset, set_temp_offset, index-1);
356
357show_temp_index(1)
358show_temp_index(2)
359show_temp_index(3)
360
361/* VID */
362static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
363		char *buf)
364{
365	struct smsc47m192_data *data = smsc47m192_update_device(dev);
366	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
367}
368static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
369
370static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
371		char *buf)
372{
373	struct smsc47m192_data *data = dev_get_drvdata(dev);
374	return sprintf(buf, "%d\n", data->vrm);
375}
376
377static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
378		const char *buf, size_t count)
379{
380	struct smsc47m192_data *data = dev_get_drvdata(dev);
381	unsigned long val;
382	int err;
383
384	err = kstrtoul(buf, 10, &val);
385	if (err)
386		return err;
387
388	data->vrm = val;
389	return count;
390}
391static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
392
393/* Alarms */
394static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
395		char *buf)
396{
397	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
398	int nr = sensor_attr->index;
399	struct smsc47m192_data *data = smsc47m192_update_device(dev);
400	return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0);
401}
402
403static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010);
404static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020);
405static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040);
406static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000);
407static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000);
408static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001);
409static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002);
410static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004);
411static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008);
412static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100);
413static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200);
414static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
415static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
416
417static struct attribute *smsc47m192_attributes[] = {
418	&sensor_dev_attr_in0_input.dev_attr.attr,
419	&sensor_dev_attr_in0_min.dev_attr.attr,
420	&sensor_dev_attr_in0_max.dev_attr.attr,
421	&sensor_dev_attr_in0_alarm.dev_attr.attr,
422	&sensor_dev_attr_in1_input.dev_attr.attr,
423	&sensor_dev_attr_in1_min.dev_attr.attr,
424	&sensor_dev_attr_in1_max.dev_attr.attr,
425	&sensor_dev_attr_in1_alarm.dev_attr.attr,
426	&sensor_dev_attr_in2_input.dev_attr.attr,
427	&sensor_dev_attr_in2_min.dev_attr.attr,
428	&sensor_dev_attr_in2_max.dev_attr.attr,
429	&sensor_dev_attr_in2_alarm.dev_attr.attr,
430	&sensor_dev_attr_in3_input.dev_attr.attr,
431	&sensor_dev_attr_in3_min.dev_attr.attr,
432	&sensor_dev_attr_in3_max.dev_attr.attr,
433	&sensor_dev_attr_in3_alarm.dev_attr.attr,
434	&sensor_dev_attr_in5_input.dev_attr.attr,
435	&sensor_dev_attr_in5_min.dev_attr.attr,
436	&sensor_dev_attr_in5_max.dev_attr.attr,
437	&sensor_dev_attr_in5_alarm.dev_attr.attr,
438	&sensor_dev_attr_in6_input.dev_attr.attr,
439	&sensor_dev_attr_in6_min.dev_attr.attr,
440	&sensor_dev_attr_in6_max.dev_attr.attr,
441	&sensor_dev_attr_in6_alarm.dev_attr.attr,
442	&sensor_dev_attr_in7_input.dev_attr.attr,
443	&sensor_dev_attr_in7_min.dev_attr.attr,
444	&sensor_dev_attr_in7_max.dev_attr.attr,
445	&sensor_dev_attr_in7_alarm.dev_attr.attr,
446
447	&sensor_dev_attr_temp1_input.dev_attr.attr,
448	&sensor_dev_attr_temp1_max.dev_attr.attr,
449	&sensor_dev_attr_temp1_min.dev_attr.attr,
450	&sensor_dev_attr_temp1_offset.dev_attr.attr,
451	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
452	&sensor_dev_attr_temp2_input.dev_attr.attr,
453	&sensor_dev_attr_temp2_max.dev_attr.attr,
454	&sensor_dev_attr_temp2_min.dev_attr.attr,
455	&sensor_dev_attr_temp2_offset.dev_attr.attr,
456	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
457	&sensor_dev_attr_temp2_fault.dev_attr.attr,
458	&sensor_dev_attr_temp3_input.dev_attr.attr,
459	&sensor_dev_attr_temp3_max.dev_attr.attr,
460	&sensor_dev_attr_temp3_min.dev_attr.attr,
461	&sensor_dev_attr_temp3_offset.dev_attr.attr,
462	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
463	&sensor_dev_attr_temp3_fault.dev_attr.attr,
464
465	&dev_attr_cpu0_vid.attr,
466	&dev_attr_vrm.attr,
467	NULL
468};
469
470static const struct attribute_group smsc47m192_group = {
471	.attrs = smsc47m192_attributes,
472};
473
474static struct attribute *smsc47m192_attributes_in4[] = {
475	&sensor_dev_attr_in4_input.dev_attr.attr,
476	&sensor_dev_attr_in4_min.dev_attr.attr,
477	&sensor_dev_attr_in4_max.dev_attr.attr,
478	&sensor_dev_attr_in4_alarm.dev_attr.attr,
479	NULL
480};
481
482static const struct attribute_group smsc47m192_group_in4 = {
483	.attrs = smsc47m192_attributes_in4,
484};
485
486static void smsc47m192_init_client(struct i2c_client *client)
487{
488	int i;
489	u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
490	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
491
492	/* select cycle mode (pause 1 sec between updates) */
493	i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
494						(sfr & 0xfd) | 0x02);
495	if (!(config & 0x01)) {
496		/* initialize alarm limits */
497		for (i = 0; i < 8; i++) {
498			i2c_smbus_write_byte_data(client,
499				SMSC47M192_REG_IN_MIN(i), 0);
500			i2c_smbus_write_byte_data(client,
501				SMSC47M192_REG_IN_MAX(i), 0xff);
502		}
503		for (i = 0; i < 3; i++) {
504			i2c_smbus_write_byte_data(client,
505				SMSC47M192_REG_TEMP_MIN[i], 0x80);
506			i2c_smbus_write_byte_data(client,
507				SMSC47M192_REG_TEMP_MAX[i], 0x7f);
508		}
509
510		/* start monitoring */
511		i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG,
512						(config & 0xf7) | 0x01);
513	}
514}
515
516/* Return 0 if detection is successful, -ENODEV otherwise */
517static int smsc47m192_detect(struct i2c_client *client,
518			     struct i2c_board_info *info)
519{
520	struct i2c_adapter *adapter = client->adapter;
521	int version;
522
523	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
524		return -ENODEV;
525
526	/* Detection criteria from sensors_detect script */
527	version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION);
528	if (i2c_smbus_read_byte_data(client,
529				SMSC47M192_REG_COMPANY_ID) == 0x55
530	 && (version & 0xf0) == 0x20
531	 && (i2c_smbus_read_byte_data(client,
532				SMSC47M192_REG_VID) & 0x70) == 0x00
533	 && (i2c_smbus_read_byte_data(client,
534				SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
535		dev_info(&adapter->dev,
536			 "found SMSC47M192 or compatible, "
537			 "version 2, stepping A%d\n", version & 0x0f);
538	} else {
539		dev_dbg(&adapter->dev,
540			"SMSC47M192 detection failed at 0x%02x\n",
541			client->addr);
542		return -ENODEV;
543	}
544
545	strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
546
547	return 0;
548}
549
550static int smsc47m192_probe(struct i2c_client *client,
551			    const struct i2c_device_id *id)
552{
553	struct smsc47m192_data *data;
554	int config;
555	int err;
556
557	data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL);
558	if (!data) {
559		err = -ENOMEM;
560		goto exit;
561	}
562
563	i2c_set_clientdata(client, data);
564	data->vrm = vid_which_vrm();
565	mutex_init(&data->update_lock);
566
567	/* Initialize the SMSC47M192 chip */
568	smsc47m192_init_client(client);
569
570	/* Register sysfs hooks */
571	err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group);
572	if (err)
573		goto exit_free;
574
575	/* Pin 110 is either in4 (+12V) or VID4 */
576	config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
577	if (!(config & 0x20)) {
578		err = sysfs_create_group(&client->dev.kobj,
579					 &smsc47m192_group_in4);
580		if (err)
581			goto exit_remove_files;
582	}
583
584	data->hwmon_dev = hwmon_device_register(&client->dev);
585	if (IS_ERR(data->hwmon_dev)) {
586		err = PTR_ERR(data->hwmon_dev);
587		goto exit_remove_files;
588	}
589
590	return 0;
591
592exit_remove_files:
593	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
594	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
595exit_free:
596	kfree(data);
597exit:
598	return err;
599}
600
601static int smsc47m192_remove(struct i2c_client *client)
602{
603	struct smsc47m192_data *data = i2c_get_clientdata(client);
604
605	hwmon_device_unregister(data->hwmon_dev);
606	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
607	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
608
609	kfree(data);
610
611	return 0;
612}
613
614static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
615{
616	struct i2c_client *client = to_i2c_client(dev);
617	struct smsc47m192_data *data = i2c_get_clientdata(client);
618	int i, config;
619
620	mutex_lock(&data->update_lock);
621
622	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
623	 || !data->valid) {
624		u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
625
626		dev_dbg(&client->dev, "Starting smsc47m192 update\n");
627
628		for (i = 0; i <= 7; i++) {
629			data->in[i] = i2c_smbus_read_byte_data(client,
630						SMSC47M192_REG_IN(i));
631			data->in_min[i] = i2c_smbus_read_byte_data(client,
632						SMSC47M192_REG_IN_MIN(i));
633			data->in_max[i] = i2c_smbus_read_byte_data(client,
634						SMSC47M192_REG_IN_MAX(i));
635		}
636		for (i = 0; i < 3; i++) {
637			data->temp[i] = i2c_smbus_read_byte_data(client,
638						SMSC47M192_REG_TEMP[i]);
639			data->temp_max[i] = i2c_smbus_read_byte_data(client,
640						SMSC47M192_REG_TEMP_MAX[i]);
641			data->temp_min[i] = i2c_smbus_read_byte_data(client,
642						SMSC47M192_REG_TEMP_MIN[i]);
643		}
644		for (i = 1; i < 3; i++)
645			data->temp_offset[i] = i2c_smbus_read_byte_data(client,
646						SMSC47M192_REG_TEMP_OFFSET(i));
647		/*
648		 * first offset is temp_offset[0] if SFR bit 4 is set,
649		 * temp_offset[1] otherwise
650		 */
651		if (sfr & 0x10) {
652			data->temp_offset[0] = data->temp_offset[1];
653			data->temp_offset[1] = 0;
654		} else
655			data->temp_offset[0] = 0;
656
657		data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
658			    & 0x0f;
659		config = i2c_smbus_read_byte_data(client,
660						  SMSC47M192_REG_CONFIG);
661		if (config & 0x20)
662			data->vid |= (i2c_smbus_read_byte_data(client,
663					SMSC47M192_REG_VID4) & 0x01) << 4;
664		data->alarms = i2c_smbus_read_byte_data(client,
665						SMSC47M192_REG_ALARM1) |
666			       (i2c_smbus_read_byte_data(client,
667						SMSC47M192_REG_ALARM2) << 8);
668
669		data->last_updated = jiffies;
670		data->valid = 1;
671	}
672
673	mutex_unlock(&data->update_lock);
674
675	return data;
676}
677
678module_i2c_driver(smsc47m192_driver);
679
680MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>");
681MODULE_DESCRIPTION("SMSC47M192 driver");
682MODULE_LICENSE("GPL");