Blame view

drivers/hwmon/lm63.c 24 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * lm63.c - driver for the National Semiconductor LM63 temperature sensor
   *          with integrated fan control
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
4
   * Copyright (C) 2004-2008  Jean Delvare <khali@linux-fr.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   * Based on the lm90 driver.
   *
   * The LM63 is a sensor chip made by National Semiconductor. It measures
   * two temperatures (its own and one external one) and the speed of one
   * fan, those speed it can additionally control. Complete datasheet can be
   * obtained from National's website at:
   *   http://www.national.com/pf/LM/LM63.html
   *
   * The LM63 is basically an LM86 with fan speed monitoring and control
   * capabilities added. It misses some of the LM86 features though:
   *  - No low limit for local temperature.
   *  - No critical limit for local temperature.
   *  - Critical limit for remote temperature can be changed only once. We
   *    will consider that the critical limit is read-only.
   *
   * The datasheet isn't very clear about what the tachometer reading is.
   * I had a explanation from National Semiconductor though. The two lower
   * bits of the read value have to be masked out. The value is still 16 bit
   * in width.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/i2c.h>
10c08f810   Jean Delvare   [PATCH] I2C: rena...
44
  #include <linux/hwmon-sysfs.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
45
46
  #include <linux/hwmon.h>
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
47
  #include <linux/mutex.h>
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
48
  #include <linux/sysfs.h>
210961c43   Guenter Roeck   hwmon: (lm63) Add...
49
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
  
  /*
   * Addresses to scan
   * Address is fully defined internally and cannot be changed.
   */
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
55
  static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
   * The LM63 registers
   */
  
  #define LM63_REG_CONFIG1		0x03
  #define LM63_REG_CONFIG2		0xBF
  #define LM63_REG_CONFIG_FAN		0x4A
  
  #define LM63_REG_TACH_COUNT_MSB		0x47
  #define LM63_REG_TACH_COUNT_LSB		0x46
  #define LM63_REG_TACH_LIMIT_MSB		0x49
  #define LM63_REG_TACH_LIMIT_LSB		0x48
  
  #define LM63_REG_PWM_VALUE		0x4C
  #define LM63_REG_PWM_FREQ		0x4D
  
  #define LM63_REG_LOCAL_TEMP		0x00
  #define LM63_REG_LOCAL_HIGH		0x05
  
  #define LM63_REG_REMOTE_TEMP_MSB	0x01
  #define LM63_REG_REMOTE_TEMP_LSB	0x10
  #define LM63_REG_REMOTE_OFFSET_MSB	0x11
  #define LM63_REG_REMOTE_OFFSET_LSB	0x12
  #define LM63_REG_REMOTE_HIGH_MSB	0x07
  #define LM63_REG_REMOTE_HIGH_LSB	0x13
  #define LM63_REG_REMOTE_LOW_MSB		0x08
  #define LM63_REG_REMOTE_LOW_LSB		0x14
  #define LM63_REG_REMOTE_TCRIT		0x19
  #define LM63_REG_REMOTE_TCRIT_HYST	0x21
  
  #define LM63_REG_ALERT_STATUS		0x02
  #define LM63_REG_ALERT_MASK		0x16
  
  #define LM63_REG_MAN_ID			0xFE
  #define LM63_REG_CHIP_ID		0xFF
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
92
93
  #define LM96163_REG_REMOTE_TEMP_U_MSB	0x31
  #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
210961c43   Guenter Roeck   hwmon: (lm63) Add...
94
  #define LM96163_REG_CONFIG_ENHANCED	0x45
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
  /*
   * Conversions and various macros
   * For tachometer counts, the LM63 uses 16-bit values.
   * For local temperature and high limit, remote critical limit and hysteresis
44bbe87e9   Steven Cole   [PATCH] Spelling ...
99
   * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
   * For remote temperature, low and high limits, it uses signed 11-bit values
44bbe87e9   Steven Cole   [PATCH] Spelling ...
101
   * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
102
103
104
   * For LM64 the actual remote diode temperature is 16 degree Celsius higher
   * than the register reading. Remote temperature setpoints have to be
   * adapted accordingly.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
111
112
113
114
115
   */
  
  #define FAN_FROM_REG(reg)	((reg) == 0xFFFC || (reg) == 0 ? 0 : \
  				 5400000 / (reg))
  #define FAN_TO_REG(val)		((val) <= 82 ? 0xFFFC : \
  				 (5400000 / (val)) & 0xFFFC)
  #define TEMP8_FROM_REG(reg)	((reg) * 1000)
  #define TEMP8_TO_REG(val)	((val) <= -128000 ? -128 : \
  				 (val) >= 127000 ? 127 : \
  				 (val) < 0 ? ((val) - 500) / 1000 : \
  				 ((val) + 500) / 1000)
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
116
117
118
  #define TEMP8U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255000 ? 255 : \
  				 ((val) + 500) / 1000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
123
  #define TEMP11_FROM_REG(reg)	((reg) / 32 * 125)
  #define TEMP11_TO_REG(val)	((val) <= -128000 ? 0x8000 : \
  				 (val) >= 127875 ? 0x7FE0 : \
  				 (val) < 0 ? ((val) - 62) / 125 * 32 : \
  				 ((val) + 62) / 125 * 32)
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
124
125
126
  #define TEMP11U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255875 ? 0xFFE0 : \
  				 ((val) + 62) / 125 * 32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
  #define HYST_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 127000 ? 127 : \
  				 ((val) + 500) / 1000)
  
  /*
   * Functions declaration
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
134
135
136
  static int lm63_probe(struct i2c_client *client,
  		      const struct i2c_device_id *id);
  static int lm63_remove(struct i2c_client *client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  
  static struct lm63_data *lm63_update_device(struct device *dev);
310ec7921   Jean Delvare   i2c: Drop the kin...
139
  static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  static void lm63_init_client(struct i2c_client *client);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
141
  enum chips { lm63, lm64, lm96163 };
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
142

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
  /*
   * Driver data (common to all clients)
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
146
  static const struct i2c_device_id lm63_id[] = {
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
147
148
  	{ "lm63", lm63 },
  	{ "lm64", lm64 },
210961c43   Guenter Roeck   hwmon: (lm63) Add...
149
  	{ "lm96163", lm96163 },
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
150
151
152
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, lm63_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  static struct i2c_driver lm63_driver = {
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
154
  	.class		= I2C_CLASS_HWMON,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
155
  	.driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
156
157
  		.name	= "lm63",
  	},
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
158
159
160
161
  	.probe		= lm63_probe,
  	.remove		= lm63_remove,
  	.id_table	= lm63_id,
  	.detect		= lm63_detect,
c3813d6af   Jean Delvare   i2c: Get rid of s...
162
  	.address_list	= normal_i2c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
  };
  
  /*
   * Client data (each client gets its own)
   */
  
  struct lm63_data {
1beeffe43   Tony Jones   hwmon: Convert fr...
170
  	struct device *hwmon_dev;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
171
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
  	char valid; /* zero until following fields are valid */
  	unsigned long last_updated; /* in jiffies */
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
174
175
  	int kind;
  	int temp2_offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
  
  	/* registers values */
  	u8 config, config_fan;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
179
180
  	u16 fan[2];	/* 0: input
  			   1: low limit */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
  	u8 pwm1_freq;
  	u8 pwm1_value;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
183
184
185
  	s8 temp8[3];	/* 0: local input
  			   1: local high limit
  			   2: remote critical limit */
786375f72   Guenter Roeck   hwmon: (lm63) Add...
186
  	s16 temp11[4];	/* 0: remote input
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
187
  			   1: remote low limit
786375f72   Guenter Roeck   hwmon: (lm63) Add...
188
189
  			   2: remote high limit
  			   3: remote offset */
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
190
  	u16 temp11u;	/* remote input (unsigned) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  	u8 temp2_crit_hyst;
  	u8 alarms;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
193
  	bool pwm_highres;
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
194
  	bool remote_unsigned; /* true if unsigned remote upper limits */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  };
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
196
197
198
199
200
201
  static inline int temp8_from_reg(struct lm63_data *data, int nr)
  {
  	if (data->remote_unsigned)
  		return TEMP8_FROM_REG((u8)data->temp8[nr]);
  	return TEMP8_FROM_REG(data->temp8[nr]);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
  /*
   * Sysfs callback functions and files
   */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
205
206
207
208
209
210
211
  static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
  			char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan[attr->index]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
214
215
  static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
  		       const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
219
220
221
222
223
224
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
226
  	mutex_lock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
227
  	data->fan[1] = FAN_TO_REG(val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
229
  				  data->fan[1] & 0xFF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
231
  				  data->fan[1] >> 8);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
232
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
  	return count;
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
235
236
  static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
  			 char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
  {
  	struct lm63_data *data = lm63_update_device(dev);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
239
240
241
242
243
244
  	int pwm;
  
  	if (data->pwm_highres)
  		pwm = data->pwm1_value;
  	else
  		pwm = data->pwm1_value >= 2 * data->pwm1_freq ?
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  		       255 : (data->pwm1_value * 255 + data->pwm1_freq) /
210961c43   Guenter Roeck   hwmon: (lm63) Add...
246
247
248
249
  		       (2 * data->pwm1_freq);
  
  	return sprintf(buf, "%d
  ", pwm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
251
252
  static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
  			const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
  	unsigned long val;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
257
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
  	if (!(data->config_fan & 0x20)) /* register is read-only */
  		return -EPERM;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
260
261
262
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
263
  	val = SENSORS_LIMIT(val, 0, 255);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
264
  	mutex_lock(&data->update_lock);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
265
  	data->pwm1_value = data->pwm_highres ? val :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  			   (val * data->pwm1_freq * 2 + 127) / 255;
  	i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
268
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	return count;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
271
272
  static ssize_t show_pwm1_enable(struct device *dev,
  				struct device_attribute *dummy, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%d
  ", data->config_fan & 0x20 ? 1 : 2);
  }
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
278
279
280
281
282
283
284
285
286
  /*
   * There are 8bit registers for both local(temp1) and remote(temp2) sensor.
   * For remote sensor registers temp2_offset has to be considered,
   * for local sensor it must not.
   * So we need separate 8bit accessors for local and remote sensor.
   */
  static ssize_t show_local_temp8(struct device *dev,
  				struct device_attribute *devattr,
  				char *buf)
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
287
288
289
290
291
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP8_FROM_REG(data->temp8[attr->index]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
293

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
294
295
296
297
298
299
  static ssize_t show_remote_temp8(struct device *dev,
  				 struct device_attribute *devattr,
  				 char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm63_data *data = lm63_update_device(dev);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
300
301
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, attr->index)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
302
303
  		       + data->temp2_offset);
  }
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
304
305
  static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
  			 const char *buf, size_t count)
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
306
  {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
307
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
308
309
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
310
311
  	int nr = attr->index;
  	int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
312
313
  	long val;
  	int err;
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
314
  	int temp;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
315
316
317
318
  
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
319

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
320
  	mutex_lock(&data->update_lock);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
321
322
323
324
325
326
327
328
329
330
  	if (nr == 2) {
  		if (data->remote_unsigned)
  			temp = TEMP8U_TO_REG(val - data->temp2_offset);
  		else
  			temp = TEMP8_TO_REG(val - data->temp2_offset);
  	} else {
  		temp = TEMP8_TO_REG(val);
  	}
  	data->temp8[nr] = temp;
  	i2c_smbus_write_byte_data(client, reg, temp);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
331
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
332
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
334
335
336
337
338
339
  
  static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
  			   char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm63_data *data = lm63_update_device(dev);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  	int nr = attr->index;
  	int temp;
  
  	if (!nr) {
  		/*
  		 * Use unsigned temperature unless its value is zero.
  		 * If it is zero, use signed temperature.
  		 */
  		if (data->temp11u)
  			temp = TEMP11_FROM_REG(data->temp11u);
  		else
  			temp = TEMP11_FROM_REG(data->temp11[nr]);
  	} else {
  		if (data->remote_unsigned && nr == 2)
  			temp = TEMP11_FROM_REG((u16)data->temp11[nr]);
  		else
  			temp = TEMP11_FROM_REG(data->temp11[nr]);
  	}
  	return sprintf(buf, "%d
  ", temp + data->temp2_offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
361
362
363
364
  
  static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
  			  const char *buf, size_t count)
  {
786375f72   Guenter Roeck   hwmon: (lm63) Add...
365
  	static const u8 reg[6] = {
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
366
367
368
369
  		LM63_REG_REMOTE_LOW_MSB,
  		LM63_REG_REMOTE_LOW_LSB,
  		LM63_REG_REMOTE_HIGH_MSB,
  		LM63_REG_REMOTE_HIGH_LSB,
786375f72   Guenter Roeck   hwmon: (lm63) Add...
370
371
  		LM63_REG_REMOTE_OFFSET_MSB,
  		LM63_REG_REMOTE_OFFSET_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
372
373
374
375
376
  	};
  
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
377
378
  	long val;
  	int err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
379
  	int nr = attr->index;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
380
381
382
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
383
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
384
385
386
387
  	if (data->remote_unsigned && nr == 2)
  		data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset);
  	else
  		data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
388
389
390
391
  	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
  				  data->temp11[nr] >> 8);
  	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
  				  data->temp11[nr] & 0xff);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
392
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
393
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395

662bda283   Guenter Roeck   hwmon: (lm63) Fix...
396
397
398
399
400
401
  /*
   * Hysteresis register holds a relative value, while we want to present
   * an absolute to user-space
   */
  static ssize_t show_temp2_crit_hyst(struct device *dev,
  				    struct device_attribute *dummy, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
  {
  	struct lm63_data *data = lm63_update_device(dev);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
404
405
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, 2)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
406
  		       + data->temp2_offset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  		       - TEMP8_FROM_REG(data->temp2_crit_hyst));
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
409
410
411
412
413
414
  /*
   * And now the other way around, user-space provides an absolute
   * hysteresis value and we have to store a relative one
   */
  static ssize_t set_temp2_crit_hyst(struct device *dev,
  				   struct device_attribute *dummy,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
415
  				   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
419
420
  	long val;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  	long hyst;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
422
423
424
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
425
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
426
  	hyst = temp8_from_reg(data, 2) + data->temp2_offset - val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
  	i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
  				  HYST_TO_REG(hyst));
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
429
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
  	return count;
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
432
433
  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
  			   char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
438
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%u
  ", data->alarms);
  }
2d45771e6   Jean Delvare   hwmon: Add indivi...
439
440
441
442
443
444
445
446
447
448
  static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr,
  			  char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm63_data *data = lm63_update_device(dev);
  	int bitnr = attr->index;
  
  	return sprintf(buf, "%u
  ", (data->alarms >> bitnr) & 1);
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
449
450
451
  static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
  static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
  	set_fan, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
  
  static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
  static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
455
456
  static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
457
  	set_temp8, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
459
460
461
462
463
  static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 1);
  static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 2);
786375f72   Guenter Roeck   hwmon: (lm63) Add...
464
465
  static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 3);
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
466
  static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
467
  	set_temp8, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
  static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
  	set_temp2_crit_hyst);
2d45771e6   Jean Delvare   hwmon: Add indivi...
470
471
472
  /* Individual alarm files */
  static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
7817a39e6   Jean Delvare   hwmon: Fault file...
473
  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
2d45771e6   Jean Delvare   hwmon: Add indivi...
474
475
476
477
  static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
  /* Raw alarm file for compatibility */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
479
480
481
482
483
484
485
486
  static struct attribute *lm63_attributes[] = {
  	&dev_attr_pwm1.attr,
  	&dev_attr_pwm1_enable.attr,
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
786375f72   Guenter Roeck   hwmon: (lm63) Add...
487
  	&sensor_dev_attr_temp2_offset.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
488
489
490
491
  	&sensor_dev_attr_temp2_crit.dev_attr.attr,
  	&dev_attr_temp2_crit_hyst.attr,
  
  	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
7817a39e6   Jean Delvare   hwmon: Fault file...
492
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
493
494
495
496
497
498
  	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
  	&dev_attr_alarms.attr,
  	NULL
  };
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  /*
   * On LM63, temp2_crit can be set only once, which should be job
   * of the bootloader.
   * On LM64, temp2_crit can always be set.
   * On LM96163, temp2_crit can be set if bit 1 of the configuration
   * register is true.
   */
  static umode_t lm63_attribute_mode(struct kobject *kobj,
  				   struct attribute *attr, int index)
  {
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
  
  	if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr
  	    && (data->kind == lm64 ||
  		(data->kind == lm96163 && (data->config & 0x02))))
  		return attr->mode | S_IWUSR;
  
  	return attr->mode;
  }
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
520
  static const struct attribute_group lm63_group = {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
521
  	.is_visible = lm63_attribute_mode,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  	.attrs = lm63_attributes,
  };
  
  static struct attribute *lm63_attributes_fan1[] = {
  	&sensor_dev_attr_fan1_input.dev_attr.attr,
  	&sensor_dev_attr_fan1_min.dev_attr.attr,
  
  	&sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group lm63_group_fan1 = {
  	.attrs = lm63_attributes_fan1,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
  /*
   * Real code
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
539
  /* Return 0 if detection is successful, -ENODEV otherwise */
310ec7921   Jean Delvare   i2c: Drop the kin...
540
  static int lm63_detect(struct i2c_client *new_client,
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
541
  		       struct i2c_board_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  {
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
543
  	struct i2c_adapter *adapter = new_client->adapter;
52df6440a   Jean Delvare   hwmon: Clean up d...
544
545
  	u8 man_id, chip_id, reg_config1, reg_config2;
  	u8 reg_alert_status, reg_alert_mask;
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
546
  	int address = new_client->addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
549
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550

52df6440a   Jean Delvare   hwmon: Clean up d...
551
552
553
554
555
556
557
558
559
560
561
562
563
  	man_id = i2c_smbus_read_byte_data(new_client, LM63_REG_MAN_ID);
  	chip_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CHIP_ID);
  
  	reg_config1 = i2c_smbus_read_byte_data(new_client,
  		      LM63_REG_CONFIG1);
  	reg_config2 = i2c_smbus_read_byte_data(new_client,
  		      LM63_REG_CONFIG2);
  	reg_alert_status = i2c_smbus_read_byte_data(new_client,
  			   LM63_REG_ALERT_STATUS);
  	reg_alert_mask = i2c_smbus_read_byte_data(new_client,
  			 LM63_REG_ALERT_MASK);
  
  	if (man_id != 0x01 /* National Semiconductor */
52df6440a   Jean Delvare   hwmon: Clean up d...
564
565
566
567
568
569
570
571
572
  	 || (reg_config1 & 0x18) != 0x00
  	 || (reg_config2 & 0xF8) != 0x00
  	 || (reg_alert_status & 0x20) != 0x00
  	 || (reg_alert_mask & 0xA4) != 0xA4) {
  		dev_dbg(&adapter->dev,
  			"Unsupported chip (man_id=0x%02X, chip_id=0x%02X)
  ",
  			man_id, chip_id);
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  	}
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
574
575
576
577
  	if (chip_id == 0x41 && address == 0x4c)
  		strlcpy(info->type, "lm63", I2C_NAME_SIZE);
  	else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
  		strlcpy(info->type, "lm64", I2C_NAME_SIZE);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
578
579
  	else if (chip_id == 0x49 && address == 0x4c)
  		strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
580
581
  	else
  		return -ENODEV;
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  
  	return 0;
  }
  
  static int lm63_probe(struct i2c_client *new_client,
  		      const struct i2c_device_id *id)
  {
  	struct lm63_data *data;
  	int err;
  
  	data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL);
  	if (!data) {
  		err = -ENOMEM;
  		goto exit;
  	}
  
  	i2c_set_clientdata(new_client, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
  	data->valid = 0;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
600
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
602
603
604
605
606
607
  	/* Set the device type */
  	data->kind = id->driver_data;
  	if (data->kind == lm64)
  		data->temp2_offset = 16000;
  
  	/* Initialize chip */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
609
610
  	lm63_init_client(new_client);
  
  	/* Register sysfs hooks */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
611
612
  	err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
  	if (err)
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
613
  		goto exit_free;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
614
  	if (data->config & 0x04) { /* tachometer enabled */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
615
616
617
  		err = sysfs_create_group(&new_client->dev.kobj,
  					 &lm63_group_fan1);
  		if (err)
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
618
  			goto exit_remove_files;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
619
  	}
1beeffe43   Tony Jones   hwmon: Convert fr...
620
621
622
  	data->hwmon_dev = hwmon_device_register(&new_client->dev);
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
623
  		goto exit_remove_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
  
  	return 0;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
627
628
629
  exit_remove_files:
  	sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
  	sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
632
633
634
  exit_free:
  	kfree(data);
  exit:
  	return err;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
635
636
637
638
  /*
   * Ideally we shouldn't have to initialize anything, since the BIOS
   * should have taken care of everything
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
643
644
645
646
647
648
  static void lm63_init_client(struct i2c_client *client)
  {
  	struct lm63_data *data = i2c_get_clientdata(client);
  
  	data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
  	data->config_fan = i2c_smbus_read_byte_data(client,
  						    LM63_REG_CONFIG_FAN);
  
  	/* Start converting if needed */
  	if (data->config & 0x40) { /* standby */
898eb71cb   Joe Perches   Add missing newli...
649
650
  		dev_dbg(&client->dev, "Switching to operational mode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
656
657
658
659
  		data->config &= 0xA7;
  		i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
  					  data->config);
  	}
  
  	/* We may need pwm1_freq before ever updating the client data */
  	data->pwm1_freq = i2c_smbus_read_byte_data(client, LM63_REG_PWM_FREQ);
  	if (data->pwm1_freq == 0)
  		data->pwm1_freq = 1;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
660
  	/*
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
661
662
  	 * For LM96163, check if high resolution PWM
  	 * and unsigned temperature format is enabled.
210961c43   Guenter Roeck   hwmon: (lm63) Add...
663
664
665
666
667
668
669
670
671
  	 */
  	if (data->kind == lm96163) {
  		u8 config_enhanced
  		  = i2c_smbus_read_byte_data(client,
  					     LM96163_REG_CONFIG_ENHANCED);
  		if ((config_enhanced & 0x10)
  		    && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
  			data->pwm_highres = true;
  		if (config_enhanced & 0x08)
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
672
  			data->remote_unsigned = true;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
673
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  	/* Show some debug info about the LM63 configuration */
  	dev_dbg(&client->dev, "Alert/tach pin configured for %s
  ",
  		(data->config & 0x04) ? "tachometer input" :
  		"alert output");
  	dev_dbg(&client->dev, "PWM clock %s kHz, output frequency %u Hz
  ",
  		(data->config_fan & 0x08) ? "1.4" : "360",
  		((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq);
  	dev_dbg(&client->dev, "PWM output active %s, %s mode
  ",
  		(data->config_fan & 0x10) ? "low" : "high",
  		(data->config_fan & 0x20) ? "manual" : "auto");
  }
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
688
  static int lm63_remove(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  {
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
690
  	struct lm63_data *data = i2c_get_clientdata(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691

1beeffe43   Tony Jones   hwmon: Convert fr...
692
  	hwmon_device_unregister(data->hwmon_dev);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
693
694
  	sysfs_remove_group(&client->dev.kobj, &lm63_group);
  	sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
695

943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
696
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
700
701
702
703
  	return 0;
  }
  
  static struct lm63_data *lm63_update_device(struct device *dev)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
704
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
  
  	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
  		if (data->config & 0x04) { /* tachometer enabled  */
  			/* order matters for fan1_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
709
710
711
712
713
714
715
716
  			data->fan[0] = i2c_smbus_read_byte_data(client,
  				       LM63_REG_TACH_COUNT_LSB) & 0xFC;
  			data->fan[0] |= i2c_smbus_read_byte_data(client,
  					LM63_REG_TACH_COUNT_MSB) << 8;
  			data->fan[1] = (i2c_smbus_read_byte_data(client,
  					LM63_REG_TACH_LIMIT_LSB) & 0xFC)
  				     | (i2c_smbus_read_byte_data(client,
  					LM63_REG_TACH_LIMIT_MSB) << 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
719
720
721
722
723
724
  		}
  
  		data->pwm1_freq = i2c_smbus_read_byte_data(client,
  				  LM63_REG_PWM_FREQ);
  		if (data->pwm1_freq == 0)
  			data->pwm1_freq = 1;
  		data->pwm1_value = i2c_smbus_read_byte_data(client,
  				   LM63_REG_PWM_VALUE);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
725
726
727
728
  		data->temp8[0] = i2c_smbus_read_byte_data(client,
  				 LM63_REG_LOCAL_TEMP);
  		data->temp8[1] = i2c_smbus_read_byte_data(client,
  				 LM63_REG_LOCAL_HIGH);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
  
  		/* order matters for temp2_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
731
732
733
734
735
  		data->temp11[0] = i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_TEMP_MSB) << 8;
  		data->temp11[0] |= i2c_smbus_read_byte_data(client,
  				   LM63_REG_REMOTE_TEMP_LSB);
  		data->temp11[1] = (i2c_smbus_read_byte_data(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
738
  				  LM63_REG_REMOTE_LOW_MSB) << 8)
  				| i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_LOW_LSB);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
739
740
741
742
  		data->temp11[2] = (i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_HIGH_MSB) << 8)
  				| i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_HIGH_LSB);
786375f72   Guenter Roeck   hwmon: (lm63) Add...
743
744
745
746
  		data->temp11[3] = (i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_OFFSET_MSB) << 8)
  				| i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_OFFSET_LSB);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
747
748
749
750
751
752
  
  		if (data->kind == lm96163)
  			data->temp11u = (i2c_smbus_read_byte_data(client,
  					LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
  				      | i2c_smbus_read_byte_data(client,
  					LM96163_REG_REMOTE_TEMP_U_LSB);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
753
754
  		data->temp8[2] = i2c_smbus_read_byte_data(client,
  				 LM63_REG_REMOTE_TCRIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
757
758
759
760
761
762
763
  		data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
  					LM63_REG_REMOTE_TCRIT_HYST);
  
  		data->alarms = i2c_smbus_read_byte_data(client,
  			       LM63_REG_ALERT_STATUS) & 0x7F;
  
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
764
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  
  	return data;
  }
  
  static int __init sensors_lm63_init(void)
  {
  	return i2c_add_driver(&lm63_driver);
  }
  
  static void __exit sensors_lm63_exit(void)
  {
  	i2c_del_driver(&lm63_driver);
  }
  
  MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
  MODULE_DESCRIPTION("LM63 driver");
  MODULE_LICENSE("GPL");
  
  module_init(sensors_lm63_init);
  module_exit(sensors_lm63_exit);