Blame view

drivers/hwmon/lm63.c 26.3 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
   * The LM63 registers
   */
  
  #define LM63_REG_CONFIG1		0x03
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
62
  #define LM63_REG_CONVRATE		0x04
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
92
  #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...
93
94
  #define LM96163_REG_REMOTE_TEMP_U_MSB	0x31
  #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
210961c43   Guenter Roeck   hwmon: (lm63) Add...
95
  #define LM96163_REG_CONFIG_ENHANCED	0x45
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
96
97
98
99
  #define LM63_MAX_CONVRATE		9
  
  #define LM63_MAX_CONVRATE_HZ		32
  #define LM96163_MAX_CONVRATE_HZ		26
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
  /*
   * 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 ...
104
   * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
   * For remote temperature, low and high limits, it uses signed 11-bit values
44bbe87e9   Steven Cole   [PATCH] Spelling ...
106
   * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
107
108
109
   * 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
110
111
112
113
114
115
116
117
118
119
120
   */
  
  #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...
121
122
123
  #define TEMP8U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255000 ? 255 : \
  				 ((val) + 500) / 1000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
128
  #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...
129
130
131
  #define TEMP11U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255875 ? 0xFFE0 : \
  				 ((val) + 62) / 125 * 32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
  #define HYST_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 127000 ? 127 : \
  				 ((val) + 500) / 1000)
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
135
136
  #define UPDATE_INTERVAL(max, rate) \
  			((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
  /*
   * Functions declaration
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
140
141
142
  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
143
144
  
  static struct lm63_data *lm63_update_device(struct device *dev);
310ec7921   Jean Delvare   i2c: Drop the kin...
145
  static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  static void lm63_init_client(struct i2c_client *client);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
147
  enum chips { lm63, lm64, lm96163 };
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
148

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
  /*
   * Driver data (common to all clients)
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
152
  static const struct i2c_device_id lm63_id[] = {
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
153
154
  	{ "lm63", lm63 },
  	{ "lm64", lm64 },
210961c43   Guenter Roeck   hwmon: (lm63) Add...
155
  	{ "lm96163", lm96163 },
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
156
157
158
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, lm63_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  static struct i2c_driver lm63_driver = {
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
160
  	.class		= I2C_CLASS_HWMON,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
161
  	.driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
162
163
  		.name	= "lm63",
  	},
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
164
165
166
167
  	.probe		= lm63_probe,
  	.remove		= lm63_remove,
  	.id_table	= lm63_id,
  	.detect		= lm63_detect,
c3813d6af   Jean Delvare   i2c: Get rid of s...
168
  	.address_list	= normal_i2c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
173
174
175
  };
  
  /*
   * Client data (each client gets its own)
   */
  
  struct lm63_data {
1beeffe43   Tony Jones   hwmon: Convert fr...
176
  	struct device *hwmon_dev;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
177
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
  	char valid; /* zero until following fields are valid */
  	unsigned long last_updated; /* in jiffies */
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
180
  	enum chips kind;
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
181
  	int temp2_offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
183
184
  	int update_interval;	/* in milliseconds */
  	int max_convrate_hz;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
  	/* registers values */
  	u8 config, config_fan;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
187
188
  	u16 fan[2];	/* 0: input
  			   1: low limit */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
  	u8 pwm1_freq;
  	u8 pwm1_value;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
191
192
193
  	s8 temp8[3];	/* 0: local input
  			   1: local high limit
  			   2: remote critical limit */
786375f72   Guenter Roeck   hwmon: (lm63) Add...
194
  	s16 temp11[4];	/* 0: remote input
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
195
  			   1: remote low limit
786375f72   Guenter Roeck   hwmon: (lm63) Add...
196
197
  			   2: remote high limit
  			   3: remote offset */
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
198
  	u16 temp11u;	/* remote input (unsigned) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  	u8 temp2_crit_hyst;
  	u8 alarms;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
201
  	bool pwm_highres;
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
202
  	bool remote_unsigned; /* true if unsigned remote upper limits */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  };
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
204
205
206
207
208
209
  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
210
211
212
  /*
   * Sysfs callback functions and files
   */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
213
214
215
216
217
218
219
  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
220
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
222
223
  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
224
225
226
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
227
228
229
230
231
232
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
234
  	mutex_lock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
235
  	data->fan[1] = FAN_TO_REG(val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
237
  				  data->fan[1] & 0xFF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
239
  				  data->fan[1] >> 8);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
240
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
  	return count;
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
243
244
  static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
  			 char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
  {
  	struct lm63_data *data = lm63_update_device(dev);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
247
248
249
250
251
252
  	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
253
  		       255 : (data->pwm1_value * 255 + data->pwm1_freq) /
210961c43   Guenter Roeck   hwmon: (lm63) Add...
254
255
256
257
  		       (2 * data->pwm1_freq);
  
  	return sprintf(buf, "%d
  ", pwm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
259
260
  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
261
262
263
264
  {
  	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...
265
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  	if (!(data->config_fan & 0x20)) /* register is read-only */
  		return -EPERM;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
268
269
270
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
271
  	val = SENSORS_LIMIT(val, 0, 255);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
272
  	mutex_lock(&data->update_lock);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
273
  	data->pwm1_value = data->pwm_highres ? val :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
  			   (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...
276
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
  	return count;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
279
280
  static ssize_t show_pwm1_enable(struct device *dev,
  				struct device_attribute *dummy, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
285
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%d
  ", data->config_fan & 0x20 ? 1 : 2);
  }
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
286
287
288
289
290
291
292
293
294
  /*
   * 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...
295
296
297
298
299
  {
  	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
300
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
301

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
302
303
304
305
306
307
  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...
308
309
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, attr->index)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
310
311
  		       + data->temp2_offset);
  }
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
312
313
  static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
  			 const char *buf, size_t count)
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
314
  {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
315
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
316
317
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
318
319
  	int nr = attr->index;
  	int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
320
321
  	long val;
  	int err;
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
322
  	int temp;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
323
324
325
326
  
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
327

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
328
  	mutex_lock(&data->update_lock);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
329
330
331
332
333
334
335
336
337
338
  	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...
339
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
340
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
342
343
344
345
346
347
  
  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...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  	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
368
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
369
370
371
372
  
  static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
  			  const char *buf, size_t count)
  {
786375f72   Guenter Roeck   hwmon: (lm63) Add...
373
  	static const u8 reg[6] = {
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
374
375
376
377
  		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...
378
379
  		LM63_REG_REMOTE_OFFSET_MSB,
  		LM63_REG_REMOTE_OFFSET_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
380
381
382
383
384
  	};
  
  	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...
385
386
  	long val;
  	int err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
387
  	int nr = attr->index;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
388
389
390
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
391
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
392
393
394
395
  	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...
396
397
398
399
  	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...
400
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
401
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403

662bda283   Guenter Roeck   hwmon: (lm63) Fix...
404
405
406
407
408
409
  /*
   * 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
410
411
  {
  	struct lm63_data *data = lm63_update_device(dev);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
412
413
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, 2)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
414
  		       + data->temp2_offset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  		       - TEMP8_FROM_REG(data->temp2_crit_hyst));
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
417
418
419
420
421
422
  /*
   * 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...
423
  				   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
427
428
  	long val;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  	long hyst;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
430
431
432
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
433
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
434
  	hyst = temp8_from_reg(data, 2) + data->temp2_offset - val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
  	i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
  				  HYST_TO_REG(hyst));
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
437
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  	return count;
  }
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  /*
   * Set conversion rate.
   * client->update_lock must be held when calling this function.
   */
  static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
  			      unsigned int interval)
  {
  	int i;
  	unsigned int update_interval;
  
  	/* Shift calculations to avoid rounding errors */
  	interval <<= 6;
  
  	/* find the nearest update rate */
  	update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
  	  / data->max_convrate_hz;
  	for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
  		if (interval >= update_interval * 3 / 4)
  			break;
  
  	i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
  	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
  }
  
  static ssize_t show_update_interval(struct device *dev,
  				    struct device_attribute *attr, char *buf)
  {
  	struct lm63_data *data = dev_get_drvdata(dev);
  
  	return sprintf(buf, "%u
  ", data->update_interval);
  }
  
  static ssize_t set_update_interval(struct device *dev,
  				   struct device_attribute *attr,
  				   const char *buf, size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
  
  	mutex_lock(&data->update_lock);
  	lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
492
493
  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
  			   char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%u
  ", data->alarms);
  }
2d45771e6   Jean Delvare   hwmon: Add indivi...
499
500
501
502
503
504
505
506
507
508
  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...
509
510
511
  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
512
513
514
  
  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...
515
516
  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...
517
  	set_temp8, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
519
520
521
522
523
  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...
524
525
  static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 3);
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
526
  static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
527
  	set_temp8, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
  static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
  	set_temp2_crit_hyst);
2d45771e6   Jean Delvare   hwmon: Add indivi...
530
531
532
  /* 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...
533
  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
2d45771e6   Jean Delvare   hwmon: Add indivi...
534
535
536
537
  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
538
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
539
540
  static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
  		   set_update_interval);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
541
542
543
544
545
546
547
548
  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...
549
  	&sensor_dev_attr_temp2_offset.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
550
551
552
553
  	&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...
554
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
555
556
557
558
  	&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,
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
559
  	&dev_attr_update_interval.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
560
561
  	NULL
  };
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  /*
   * 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...
583
  static const struct attribute_group lm63_group = {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
584
  	.is_visible = lm63_attribute_mode,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  	.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
599
600
601
  /*
   * Real code
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
602
  /* Return 0 if detection is successful, -ENODEV otherwise */
310ec7921   Jean Delvare   i2c: Drop the kin...
603
  static int lm63_detect(struct i2c_client *new_client,
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
604
  		       struct i2c_board_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  {
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
606
  	struct i2c_adapter *adapter = new_client->adapter;
52df6440a   Jean Delvare   hwmon: Clean up d...
607
608
  	u8 man_id, chip_id, reg_config1, reg_config2;
  	u8 reg_alert_status, reg_alert_mask;
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
609
  	int address = new_client->addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
612
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613

52df6440a   Jean Delvare   hwmon: Clean up d...
614
615
616
617
618
619
620
621
622
623
624
625
626
  	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...
627
628
629
630
631
632
633
634
635
  	 || (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
636
  	}
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
637
638
639
640
  	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...
641
642
  	else if (chip_id == 0x49 && address == 0x4c)
  		strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
643
644
  	else
  		return -ENODEV;
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  
  	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
662
  	data->valid = 0;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
663
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
665
666
667
668
669
670
  	/* 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
671
672
673
  	lm63_init_client(new_client);
  
  	/* Register sysfs hooks */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
674
675
  	err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
  	if (err)
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
676
  		goto exit_free;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
677
  	if (data->config & 0x04) { /* tachometer enabled */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
678
679
680
  		err = sysfs_create_group(&new_client->dev.kobj,
  					 &lm63_group_fan1);
  		if (err)
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
681
  			goto exit_remove_files;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
682
  	}
1beeffe43   Tony Jones   hwmon: Convert fr...
683
684
685
  	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...
686
  		goto exit_remove_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
  
  	return 0;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
690
691
692
  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
693
694
695
696
697
  exit_free:
  	kfree(data);
  exit:
  	return err;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
698
699
700
701
  /*
   * 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
702
703
704
  static void lm63_init_client(struct i2c_client *client)
  {
  	struct lm63_data *data = i2c_get_clientdata(client);
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
705
  	u8 convrate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
709
710
711
712
  
  	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...
713
714
  		dev_dbg(&client->dev, "Switching to operational mode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
719
720
721
722
723
  		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;
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
  	switch (data->kind) {
  	case lm63:
  	case lm64:
  		data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
  		break;
  	case lm96163:
  		data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
  		break;
  	}
  	convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
  	if (unlikely(convrate > LM63_MAX_CONVRATE))
  		convrate = LM63_MAX_CONVRATE;
  	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
  						convrate);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
738
  	/*
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
739
740
  	 * For LM96163, check if high resolution PWM
  	 * and unsigned temperature format is enabled.
210961c43   Guenter Roeck   hwmon: (lm63) Add...
741
742
743
744
745
746
747
748
749
  	 */
  	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...
750
  			data->remote_unsigned = true;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
751
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  	/* 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...
766
  static int lm63_remove(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  {
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
768
  	struct lm63_data *data = i2c_get_clientdata(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769

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

943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
774
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
778
779
780
781
  	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);
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
782
  	unsigned long next_update;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
784
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785

04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
786
787
788
789
  	next_update = data->last_updated
  	  + msecs_to_jiffies(data->update_interval) + 1;
  
  	if (time_after(jiffies, next_update) || !data->valid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
  		if (data->config & 0x04) { /* tachometer enabled  */
  			/* order matters for fan1_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
792
793
794
795
796
797
798
799
  			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
800
801
802
803
804
805
806
807
  		}
  
  		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...
808
809
810
811
  		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
812
813
  
  		/* order matters for temp2_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
814
815
816
817
818
  		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
819
820
821
  				  LM63_REG_REMOTE_LOW_MSB) << 8)
  				| i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_LOW_LSB);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
822
823
824
825
  		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...
826
827
828
829
  		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...
830
831
832
833
834
835
  
  		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...
836
837
  		data->temp8[2] = i2c_smbus_read_byte_data(client,
  				 LM63_REG_REMOTE_TCRIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
844
845
846
  		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...
847
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
  
  	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);