Blame view

drivers/hwmon/lm63.c 35.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
  
  /*
   * Addresses to scan
d93ab7807   Jean Delvare   hwmon: (lm63) Fix...
53
54
55
56
   * Address is fully defined internally and cannot be changed except for
   * LM64 which has one pin dedicated to address selection.
   * LM63 and LM96163 have address 0x4c.
   * LM64 can have address 0x18 or 0x4e.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
   */
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
58
  static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
   * The LM63 registers
   */
  
  #define LM63_REG_CONFIG1		0x03
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
65
  #define LM63_REG_CONVRATE		0x04
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
74
75
  #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
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
76
77
78
  #define LM63_REG_LUT_TEMP_HYST		0x4F
  #define LM63_REG_LUT_TEMP(nr)		(0x50 + 2 * (nr))
  #define LM63_REG_LUT_PWM(nr)		(0x51 + 2 * (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  
  #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
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
99
  #define LM96163_REG_TRUTHERM		0x30
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
100
101
  #define LM96163_REG_REMOTE_TEMP_U_MSB	0x31
  #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
210961c43   Guenter Roeck   hwmon: (lm63) Add...
102
  #define LM96163_REG_CONFIG_ENHANCED	0x45
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
103
104
105
106
  #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
107
108
109
110
  /*
   * 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 ...
111
   * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
   * For remote temperature, low and high limits, it uses signed 11-bit values
44bbe87e9   Steven Cole   [PATCH] Spelling ...
113
   * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
114
115
116
   * 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
117
118
119
120
121
122
123
124
125
126
127
   */
  
  #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...
128
129
130
  #define TEMP8U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255000 ? 255 : \
  				 ((val) + 500) / 1000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
  #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...
136
137
138
  #define TEMP11U_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 255875 ? 0xFFE0 : \
  				 ((val) + 62) / 125 * 32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  #define HYST_TO_REG(val)	((val) <= 0 ? 0 : \
  				 (val) >= 127000 ? 127 : \
  				 ((val) + 500) / 1000)
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
142
143
  #define UPDATE_INTERVAL(max, rate) \
  			((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
  /*
   * Functions declaration
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
147
148
149
  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
150
151
  
  static struct lm63_data *lm63_update_device(struct device *dev);
310ec7921   Jean Delvare   i2c: Drop the kin...
152
  static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  static void lm63_init_client(struct i2c_client *client);
210961c43   Guenter Roeck   hwmon: (lm63) Add...
154
  enum chips { lm63, lm64, lm96163 };
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
155

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

04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
192
193
  	int update_interval;	/* in milliseconds */
  	int max_convrate_hz;
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
194
  	int lut_size;		/* 8 or 12 */
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
195

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
  	/* registers values */
  	u8 config, config_fan;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
198
199
  	u16 fan[2];	/* 0: input
  			   1: low limit */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	u8 pwm1_freq;
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
201
202
203
  	u8 pwm1[13];	/* 0: current output
  			   1-12: lookup table */
  	s8 temp8[15];	/* 0: local input
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
204
  			   1: local high limit
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
205
  			   2: remote critical limit
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
206
  			   3-14: lookup table */
786375f72   Guenter Roeck   hwmon: (lm63) Add...
207
  	s16 temp11[4];	/* 0: remote input
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
208
  			   1: remote low limit
786375f72   Guenter Roeck   hwmon: (lm63) Add...
209
210
  			   2: remote high limit
  			   3: remote offset */
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
211
  	u16 temp11u;	/* remote input (unsigned) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	u8 temp2_crit_hyst;
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
213
  	u8 lut_temp_hyst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	u8 alarms;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
215
  	bool pwm_highres;
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
216
  	bool lut_temp_highres;
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
217
  	bool remote_unsigned; /* true if unsigned remote upper limits */
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
218
  	bool trutherm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  };
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
220
221
222
223
224
225
  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]);
  }
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
226
227
228
229
  static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
  {
  	return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  /*
   * Sysfs callback functions and files
   */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
233
234
235
236
237
238
239
  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
240
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
242
243
  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
244
245
246
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
247
248
249
250
251
252
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
254
  	mutex_lock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
255
  	data->fan[1] = FAN_TO_REG(val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
257
  				  data->fan[1] & 0xFF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
259
  				  data->fan[1] >> 8);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
260
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
  	return count;
  }
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
263
  static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
264
  			 char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  {
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
266
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  	struct lm63_data *data = lm63_update_device(dev);
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
268
  	int nr = attr->index;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
269
270
271
  	int pwm;
  
  	if (data->pwm_highres)
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
272
  		pwm = data->pwm1[nr];
210961c43   Guenter Roeck   hwmon: (lm63) Add...
273
  	else
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
274
275
  		pwm = data->pwm1[nr] >= 2 * data->pwm1_freq ?
  		       255 : (data->pwm1[nr] * 255 + data->pwm1_freq) /
210961c43   Guenter Roeck   hwmon: (lm63) Add...
276
277
278
279
  		       (2 * data->pwm1_freq);
  
  	return sprintf(buf, "%d
  ", pwm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
281
282
  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
283
284
285
286
  {
  	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...
287
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  	if (!(data->config_fan & 0x20)) /* register is read-only */
  		return -EPERM;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
290
291
292
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
293
  	val = SENSORS_LIMIT(val, 0, 255);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
294
  	mutex_lock(&data->update_lock);
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
295
296
297
  	data->pwm1[0] = data->pwm_highres ? val :
  			(val * data->pwm1_freq * 2 + 127) / 255;
  	i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
298
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
  	return count;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
301
302
  static ssize_t show_pwm1_enable(struct device *dev,
  				struct device_attribute *dummy, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
306
307
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%d
  ", data->config_fan & 0x20 ? 1 : 2);
  }
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
308
309
310
311
312
313
314
315
316
  /*
   * 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...
317
318
319
320
321
  {
  	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
322
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
323

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
324
325
326
327
328
329
  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...
330
331
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, attr->index)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
332
333
  		       + data->temp2_offset);
  }
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
334
335
336
337
338
339
340
341
342
343
  static ssize_t show_lut_temp(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
  ", lut_temp_from_reg(data, attr->index)
  		       + data->temp2_offset);
  }
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
344
345
  static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
  			 const char *buf, size_t count)
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
346
  {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
347
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
348
349
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
350
351
  	int nr = attr->index;
  	int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
352
353
  	long val;
  	int err;
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
354
  	int temp;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
355
356
357
358
  
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
359

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
360
  	mutex_lock(&data->update_lock);
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
361
362
363
364
365
366
367
368
369
370
  	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...
371
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
372
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
374
375
376
377
378
379
  
  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...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
  	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
400
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
401
402
403
404
  
  static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
  			  const char *buf, size_t count)
  {
786375f72   Guenter Roeck   hwmon: (lm63) Add...
405
  	static const u8 reg[6] = {
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
406
407
408
409
  		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...
410
411
  		LM63_REG_REMOTE_OFFSET_MSB,
  		LM63_REG_REMOTE_OFFSET_LSB,
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
412
413
414
415
416
  	};
  
  	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...
417
418
  	long val;
  	int err;
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
419
  	int nr = attr->index;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
420
421
422
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
423
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
424
425
426
427
  	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...
428
429
430
431
  	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...
432
  	mutex_unlock(&data->update_lock);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
433
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435

662bda283   Guenter Roeck   hwmon: (lm63) Fix...
436
437
438
439
440
441
  /*
   * 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
442
443
  {
  	struct lm63_data *data = lm63_update_device(dev);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
444
445
  	return sprintf(buf, "%d
  ", temp8_from_reg(data, 2)
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
446
  		       + data->temp2_offset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  		       - TEMP8_FROM_REG(data->temp2_crit_hyst));
  }
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
449
450
451
452
453
454
455
456
457
458
459
  static ssize_t show_lut_temp_hyst(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
  ", lut_temp_from_reg(data, attr->index)
  		       + data->temp2_offset
  		       - TEMP8_FROM_REG(data->lut_temp_hyst));
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
460
461
462
463
464
465
  /*
   * 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...
466
  				   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
470
471
  	long val;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
  	long hyst;
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
473
474
475
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
476
  	mutex_lock(&data->update_lock);
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
477
  	hyst = temp8_from_reg(data, 2) + data->temp2_offset - val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
  	i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
  				  HYST_TO_REG(hyst));
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
480
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
  	return count;
  }
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  /*
   * 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;
  }
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  static ssize_t show_type(struct device *dev, struct device_attribute *attr,
  			 char *buf)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm63_data *data = i2c_get_clientdata(client);
  
  	return sprintf(buf, data->trutherm ? "1
  " : "2
  ");
  }
  
  static ssize_t set_type(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 ret;
  	u8 reg;
  
  	ret = kstrtoul(buf, 10, &val);
  	if (ret < 0)
  		return ret;
  	if (val != 1 && val != 2)
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
  	data->trutherm = val == 1;
  	reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02;
  	i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM,
  				  reg | (data->trutherm ? 0x02 : 0x00));
  	data->valid = 0;
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
571
572
  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
  			   char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
575
576
577
  {
  	struct lm63_data *data = lm63_update_device(dev);
  	return sprintf(buf, "%u
  ", data->alarms);
  }
2d45771e6   Jean Delvare   hwmon: Add indivi...
578
579
580
581
582
583
584
585
586
587
  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...
588
589
590
  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
591

d216f6809   Jean Delvare   hwmon: (lm63) Exp...
592
  static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
  	show_lut_temp, NULL, 3);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 3);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
  	show_lut_temp, NULL, 4);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 4);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
  	show_lut_temp, NULL, 5);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 5);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
  	show_lut_temp, NULL, 6);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 6);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
  	show_lut_temp, NULL, 7);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 7);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
  	show_lut_temp, NULL, 8);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 8);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
  	show_lut_temp, NULL, 9);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 9);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
  	show_lut_temp, NULL, 10);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 10);
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
  static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO,
  	show_lut_temp, NULL, 11);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 11);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO,
  	show_lut_temp, NULL, 12);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 12);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO,
  	show_lut_temp, NULL, 13);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 13);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO,
  	show_lut_temp, NULL, 14);
  static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO,
  	show_lut_temp_hyst, NULL, 14);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
655
656
  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...
657
  	set_temp8, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
659
660
661
662
663
  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...
664
665
  static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 3);
2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
666
  static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
667
  	set_temp8, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
  static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
  	set_temp2_crit_hyst);
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
670
  static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type);
2d45771e6   Jean Delvare   hwmon: Add indivi...
671
672
673
  /* 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...
674
  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
2d45771e6   Jean Delvare   hwmon: Add indivi...
675
676
677
678
  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
679
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
680
681
  static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
  		   set_update_interval);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
682
  static struct attribute *lm63_attributes[] = {
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
683
  	&sensor_dev_attr_pwm1.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
684
  	&dev_attr_pwm1_enable.attr,
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
  	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point5_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point6_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point7_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point8_temp_hyst.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
709
710
711
712
713
  	&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...
714
  	&sensor_dev_attr_temp2_offset.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
715
716
717
718
  	&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...
719
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
720
721
722
723
  	&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...
724
  	&dev_attr_update_interval.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
725
726
  	NULL
  };
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  static struct attribute *lm63_attributes_extra_lut[] = {
  	&sensor_dev_attr_pwm1_auto_point9_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point9_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point9_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point10_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point10_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point10_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point11_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point11_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point11_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point12_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point12_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point12_temp_hyst.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group lm63_group_extra_lut = {
  	.attrs = lm63_attributes_extra_lut,
  };
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
  /*
   * 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...
767
  static const struct attribute_group lm63_group = {
94e55df48   Guenter Roeck   hwmon: (lm63) Add...
768
  	.is_visible = lm63_attribute_mode,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  	.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
783
784
785
  /*
   * Real code
   */
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
786
  /* Return 0 if detection is successful, -ENODEV otherwise */
310ec7921   Jean Delvare   i2c: Drop the kin...
787
  static int lm63_detect(struct i2c_client *new_client,
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
788
  		       struct i2c_board_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  {
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
790
  	struct i2c_adapter *adapter = new_client->adapter;
52df6440a   Jean Delvare   hwmon: Clean up d...
791
792
  	u8 man_id, chip_id, reg_config1, reg_config2;
  	u8 reg_alert_status, reg_alert_mask;
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
793
  	int address = new_client->addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
796
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797

52df6440a   Jean Delvare   hwmon: Clean up d...
798
799
800
801
802
803
804
805
806
807
808
809
810
  	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...
811
812
813
814
815
816
817
818
819
  	 || (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
820
  	}
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
821
822
823
824
  	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...
825
826
  	else if (chip_id == 0x49 && address == 0x4c)
  		strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
10f2ed31a   Matthew Garrett   hwmon: (lm63) Add...
827
828
  	else
  		return -ENODEV;
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  
  	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
846
  	data->valid = 0;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
847
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848

2778fb13b   Dirk Eibach   hwmon: (lm63) Con...
849
850
851
852
853
854
  	/* 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
855
856
857
  	lm63_init_client(new_client);
  
  	/* Register sysfs hooks */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
858
859
  	err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
  	if (err)
d5957be2f   Jean Delvare   hwmon: (lm63) Con...
860
  		goto exit_free;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
861
  	if (data->config & 0x04) { /* tachometer enabled */
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
862
863
864
  		err = sysfs_create_group(&new_client->dev.kobj,
  					 &lm63_group_fan1);
  		if (err)
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
865
  			goto exit_remove_files;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
866
  	}
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
867
868
869
870
871
  	if (data->kind == lm96163) {
  		err = device_create_file(&new_client->dev,
  					 &dev_attr_temp2_type);
  		if (err)
  			goto exit_remove_files;
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
872
873
874
875
876
  
  		err = sysfs_create_group(&new_client->dev.kobj,
  					 &lm63_group_extra_lut);
  		if (err)
  			goto exit_remove_files;
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
877
  	}
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
878

1beeffe43   Tony Jones   hwmon: Convert fr...
879
880
881
  	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...
882
  		goto exit_remove_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
  
  	return 0;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
886
887
888
  exit_remove_files:
  	sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
  	sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
889
890
891
892
893
  	if (data->kind == lm96163) {
  		device_remove_file(&new_client->dev, &dev_attr_temp2_type);
  		sysfs_remove_group(&new_client->dev.kobj,
  				   &lm63_group_extra_lut);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
897
898
  exit_free:
  	kfree(data);
  exit:
  	return err;
  }
662bda283   Guenter Roeck   hwmon: (lm63) Fix...
899
900
901
902
  /*
   * 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
903
904
905
  static void lm63_init_client(struct i2c_client *client)
  {
  	struct lm63_data *data = i2c_get_clientdata(client);
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
906
  	u8 convrate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
908
909
910
911
912
913
  
  	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...
914
915
  		dev_dbg(&client->dev, "Switching to operational mode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
918
919
  		data->config &= 0xA7;
  		i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
  					  data->config);
  	}
409c0b5bd   Jean Delvare   hwmon: (lm63) LM6...
920
921
922
  	/* Tachometer is always enabled on LM64 */
  	if (data->kind == lm64)
  		data->config |= 0x04;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
925
926
927
  
  	/* 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...
928
929
930
931
  	switch (data->kind) {
  	case lm63:
  	case lm64:
  		data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
932
  		data->lut_size = 8;
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
933
934
935
  		break;
  	case lm96163:
  		data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
936
  		data->lut_size = 12;
f496b2d4f   Guenter Roeck   hwmon: (lm63) Add...
937
938
939
  		data->trutherm
  		  = i2c_smbus_read_byte_data(client,
  					     LM96163_REG_TRUTHERM) & 0x02;
04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
940
941
942
943
944
945
946
  		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...
947
  	/*
e872c91e7   Guenter Roeck   hwmon: (lm63) Add...
948
949
  	 * For LM96163, check if high resolution PWM
  	 * and unsigned temperature format is enabled.
210961c43   Guenter Roeck   hwmon: (lm63) Add...
950
951
952
953
954
  	 */
  	if (data->kind == lm96163) {
  		u8 config_enhanced
  		  = i2c_smbus_read_byte_data(client,
  					     LM96163_REG_CONFIG_ENHANCED);
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
955
956
  		if (config_enhanced & 0x20)
  			data->lut_temp_highres = true;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
957
958
959
960
  		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...
961
  			data->remote_unsigned = true;
210961c43   Guenter Roeck   hwmon: (lm63) Add...
962
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
  	/* Show some debug info about the LM63 configuration */
409c0b5bd   Jean Delvare   hwmon: (lm63) LM6...
964
965
966
967
968
  	if (data->kind == lm63)
  		dev_dbg(&client->dev, "Alert/tach pin configured for %s
  ",
  			(data->config & 0x04) ? "tachometer input" :
  			"alert output");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
974
975
976
977
  	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...
978
  static int lm63_remove(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  {
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
980
  	struct lm63_data *data = i2c_get_clientdata(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981

1beeffe43   Tony Jones   hwmon: Convert fr...
982
  	hwmon_device_unregister(data->hwmon_dev);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
983
984
  	sysfs_remove_group(&client->dev.kobj, &lm63_group);
  	sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
985
986
987
988
  	if (data->kind == lm96163) {
  		device_remove_file(&client->dev, &dev_attr_temp2_type);
  		sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
  	}
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
989

943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
990
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
993
994
995
996
997
  	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...
998
  	unsigned long next_update;
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
999
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000

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

04738b2b2   Guenter Roeck   hwmon: (lm63) Add...
1003
1004
1005
1006
  	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
1007
1008
  		if (data->config & 0x04) { /* tachometer enabled  */
  			/* order matters for fan1_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
1009
1010
1011
1012
1013
1014
1015
1016
  			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
1017
1018
1019
1020
1021
1022
  		}
  
  		data->pwm1_freq = i2c_smbus_read_byte_data(client,
  				  LM63_REG_PWM_FREQ);
  		if (data->pwm1_freq == 0)
  			data->pwm1_freq = 1;
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
1023
1024
  		data->pwm1[0] = i2c_smbus_read_byte_data(client,
  				LM63_REG_PWM_VALUE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025

bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
1026
1027
1028
1029
  		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
1030
1031
  
  		/* order matters for temp2_input */
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
1032
1033
1034
1035
1036
  		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
1037
1038
1039
  				  LM63_REG_REMOTE_LOW_MSB) << 8)
  				| i2c_smbus_read_byte_data(client,
  				  LM63_REG_REMOTE_LOW_LSB);
bc51ae115   Jean Delvare   [PATCH] I2C: lm63...
1040
1041
1042
1043
  		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...
1044
1045
1046
1047
  		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...
1048
1049
1050
1051
1052
1053
  
  		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...
1054
1055
  		data->temp8[2] = i2c_smbus_read_byte_data(client,
  				 LM63_REG_REMOTE_TCRIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
1058
1059
1060
1061
1062
1063
1064
  		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;
  	}
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
1065
1066
  	if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
  	    !data->lut_valid) {
2fe28ab51   Jean Delvare   hwmon: (lm63) Sup...
1067
  		for (i = 0; i < data->lut_size; i++) {
d216f6809   Jean Delvare   hwmon: (lm63) Exp...
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  			data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
  					    LM63_REG_LUT_PWM(i));
  			data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
  					     LM63_REG_LUT_TEMP(i));
  		}
  		data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
  				      LM63_REG_LUT_TEMP_HYST);
  
  		data->lut_last_updated = jiffies;
  		data->lut_valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1079
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  
  	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);