Blame view

drivers/hwmon/adm1031.c 31.8 KB
74ba9207e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
3
4
5
6
7
   * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware
   *	       monitoring
   * Based on lm75.c and lm85.c
   * Supports adm1030 / adm1031
   * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
7c81c60f3   Jean Delvare   Update Jean Delva...
8
   * Reworked by Jean Delvare <jdelvare@suse.de>
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
9
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/i2c.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
16
  #include <linux/hwmon.h>
c801082d7   Jean Delvare   hwmon: (adm1031) ...
17
  #include <linux/hwmon-sysfs.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
18
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
19
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
  
  /* Following macros takes channel parameter starting from 0 to 2 */
  #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
23
  #define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #define ADM1031_REG_PWM			(0x22)
  #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
87c33daad   Jean Delvare   hwmon: (adm1031) ...
26
  #define ADM1031_REG_FAN_FILTER		(0x23)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

49dc9efed   Ira Snyder   hwmon: (adm1031) ...
28
  #define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
29
30
31
  #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
  #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
  #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32

6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
33
  #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
  
  #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
37
38
39
  #define ADM1031_REG_CONF1		0x00
  #define ADM1031_REG_CONF2		0x01
  #define ADM1031_REG_EXT_TEMP		0x06
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
  
  #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
  #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
  #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
  
  #define ADM1031_CONF2_PWM1_ENABLE	0x01
  #define ADM1031_CONF2_PWM2_ENABLE	0x02
  #define ADM1031_CONF2_TACH1_ENABLE	0x04
  #define ADM1031_CONF2_TACH2_ENABLE	0x08
  #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
87c33daad   Jean Delvare   hwmon: (adm1031) ...
50
51
  #define ADM1031_UPDATE_RATE_MASK	0x1c
  #define ADM1031_UPDATE_RATE_SHIFT	2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  /* Addresses to scan */
25e9c86d5   Mark M. Hoffman   hwmon: normal_i2c...
53
  static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

e5e9f44c2   Jean Delvare   i2c: Drop I2C_CLI...
55
  enum chips { adm1030, adm1031 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  
  typedef u8 auto_chan_table_t[8][2];
  
  /* Each client has this additional data */
  struct adm1031_data {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
61
62
  	struct i2c_client *client;
  	const struct attribute_group *groups[3];
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
63
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
  	int chip_type;
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
67
  	unsigned int update_interval;	/* In milliseconds */
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
68
69
  	/*
  	 * The chan_select_table contains the possible configurations for
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  	 * auto fan control.
  	 */
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
72
  	const auto_chan_table_t *chan_select_table;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  	u16 alarm;
  	u8 conf1;
  	u8 conf2;
  	u8 fan[2];
  	u8 fan_div[2];
  	u8 fan_min[2];
  	u8 pwm[2];
  	u8 old_pwm[2];
  	s8 temp[3];
  	u8 ext_temp[3];
  	u8 auto_temp[3];
  	u8 auto_temp_min[3];
  	u8 auto_temp_off[3];
  	u8 auto_temp_max[3];
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
87
  	s8 temp_offset[3];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
  	s8 temp_min[3];
  	s8 temp_max[3];
  	s8 temp_crit[3];
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
99
100
101
  static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
  {
  	return i2c_smbus_read_byte_data(client, reg);
  }
  
  static inline int
  adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
  {
  	return i2c_smbus_write_byte_data(client, reg, value);
  }
278ee1c84   Axel Lin   hwmon: (adm1031) ...
102
103
  static struct adm1031_data *adm1031_update_device(struct device *dev)
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
104
105
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
278ee1c84   Axel Lin   hwmon: (adm1031) ...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  	unsigned long next_update;
  	int chan;
  
  	mutex_lock(&data->update_lock);
  
  	next_update = data->last_updated
  	  + msecs_to_jiffies(data->update_interval);
  	if (time_after(jiffies, next_update) || !data->valid) {
  
  		dev_dbg(&client->dev, "Starting adm1031 update
  ");
  		for (chan = 0;
  		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
  			u8 oldh, newh;
  
  			oldh =
  			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
  			data->ext_temp[chan] =
  			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
  			newh =
  			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
  			if (newh != oldh) {
  				data->ext_temp[chan] =
  				    adm1031_read_value(client,
  						       ADM1031_REG_EXT_TEMP);
  #ifdef DEBUG
  				oldh =
  				    adm1031_read_value(client,
  						       ADM1031_REG_TEMP(chan));
  
  				/* oldh is actually newer */
  				if (newh != oldh)
  					dev_warn(&client->dev,
  					  "Remote temperature may be wrong.
  ");
  #endif
  			}
  			data->temp[chan] = newh;
  
  			data->temp_offset[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_TEMP_OFFSET(chan));
  			data->temp_min[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_TEMP_MIN(chan));
  			data->temp_max[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_TEMP_MAX(chan));
  			data->temp_crit[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_TEMP_CRIT(chan));
  			data->auto_temp[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_AUTO_TEMP(chan));
  
  		}
  
  		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
  		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
  
  		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
  		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
  		if (data->chip_type == adm1030)
  			data->alarm &= 0xc0ff;
  
  		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
  		     chan++) {
  			data->fan_div[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_FAN_DIV(chan));
  			data->fan_min[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_FAN_MIN(chan));
  			data->fan[chan] =
  			    adm1031_read_value(client,
  					       ADM1031_REG_FAN_SPEED(chan));
  			data->pwm[chan] =
  			  (adm1031_read_value(client,
  					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
  		}
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
  
  	mutex_unlock(&data->update_lock);
  
  	return data;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
  
  #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
  					((val + 500) / 1000)))
  
  #define TEMP_FROM_REG(val)		((val) * 1000)
  
  #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
201
202
203
  #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
  #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
  						      (val) | 0x70 : (val))
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
204
205
  #define FAN_FROM_REG(reg, div)		((reg) ? \
  					 (11250 * 60) / ((reg) * (div)) : 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
  
  static int FAN_TO_REG(int reg, int div)
  {
  	int tmp;
2a844c148   Guenter Roeck   hwmon: Replace SE...
210
  	tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
  	return tmp > 255 ? 255 : tmp;
  }
  
  #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
2a844c148   Guenter Roeck   hwmon: Replace SE...
215
  #define PWM_TO_REG(val)			(clamp_val((val), 0, 255) >> 4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
222
  #define PWM_FROM_REG(val)		((val) << 4)
  
  #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
  #define FAN_CHAN_TO_REG(val, reg)	\
  	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
  
  #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
223
224
  	((((val) / 500) & 0xf8) | ((reg) & 0x7))
  #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1 << ((reg) & 0x7)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
  
  #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
  
  #define AUTO_TEMP_OFF_FROM_REG(reg)		\
  	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
  
  #define AUTO_TEMP_MAX_FROM_REG(reg)		\
  	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
  	AUTO_TEMP_MIN_FROM_REG(reg))
  
  static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
  {
  	int ret;
  	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
  
  	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
  	ret = ((reg & 0xf8) |
  	       (range < 10000 ? 0 :
  		range < 20000 ? 1 :
  		range < 40000 ? 2 : range < 80000 ? 3 : 4));
  	return ret;
  }
  
  /* FAN auto control */
  #define GET_FAN_AUTO_BITFIELD(data, idx)	\
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
251
  	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
253
254
  /*
   * The tables below contains the possible values for the auto fan
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
   * control bitfields. the index in the table is the register value.
   * MSb is the auto fan control enable bit, so the four first entries
   * in the table disables auto fan control when both bitfields are zero.
   */
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
259
260
261
262
263
264
  static const auto_chan_table_t auto_channel_select_table_adm1031 = {
  	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
  	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
  	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
  	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
  	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  };
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
266
267
268
269
270
271
  static const auto_chan_table_t auto_channel_select_table_adm1030 = {
  	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
  	{ 2 /* 0b10 */		, 0 },
  	{ 0xff /* invalid */	, 0 },
  	{ 0xff /* invalid */	, 0 },
  	{ 3 /* 0b11 */		, 0 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  };
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
273
274
  /*
   * That function checks if a bitfield is valid and returns the other bitfield
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
   * nearest match if no exact match where found.
   */
  static int
ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
278
  get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
283
  {
  	int i;
  	int first_match = -1, exact_match = -1;
  	u8 other_reg_val =
  	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
284
  	if (val == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
293
294
295
  
  	for (i = 0; i < 8; i++) {
  		if ((val == (*data->chan_select_table)[i][chan]) &&
  		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
  		     other_reg_val)) {
  			/* We found an exact match */
  			exact_match = i;
  			break;
  		} else if (val == (*data->chan_select_table)[i][chan] &&
  			   first_match == -1) {
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
296
297
  			/*
  			 * Save the first match in case of an exact match has
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
298
  			 * not been found
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
  			 */
  			first_match = i;
  		}
  	}
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
303
  	if (exact_match >= 0)
ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
304
  		return exact_match;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
305
  	else if (first_match >= 0)
ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
306
  		return first_match;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
307

ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
308
  	return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
310
  static ssize_t fan_auto_channel_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
311
  				     struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
313
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", GET_FAN_AUTO_BITFIELD(data, nr));
  }
  
  static ssize_t
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
320
321
  fan_auto_channel_store(struct device *dev, struct device_attribute *attr,
  		       const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
323
324
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
325
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
326
  	long val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
  	u8 reg;
  	int ret;
  	u8 old_fan_mode;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
330
331
332
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	old_fan_mode = data->conf1;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
334
  	mutex_lock(&data->update_lock);
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
335

ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
336
337
  	ret = get_fan_auto_nearest(data, nr, val, data->conf1);
  	if (ret < 0) {
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
338
  		mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
  		return ret;
  	}
ce15a81da   Guenter Roeck   hwmon: (adm1031) ...
341
  	reg = ret;
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
342
343
  	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
  	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
345
  		if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
346
347
  			/*
  			 * Switch to Auto Fan Mode
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
348
  			 * Save PWM registers
fbb6670d9   Guenter Roeck   hwmon: (adm1031) ...
349
350
  			 * Set PWM registers to 33% Both
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
  			data->old_pwm[0] = data->pwm[0];
  			data->old_pwm[1] = data->pwm[1];
  			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
  		} else {
  			/* Switch to Manual Mode */
  			data->pwm[0] = data->old_pwm[0];
  			data->pwm[1] = data->old_pwm[1];
  			/* Restore PWM registers */
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
359
  			adm1031_write_value(client, ADM1031_REG_PWM,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
361
362
363
364
  					    data->pwm[0] | (data->pwm[1] << 4));
  		}
  	}
  	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
  	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
365
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
368
369
  static SENSOR_DEVICE_ATTR_RW(auto_fan1_channel, fan_auto_channel, 0);
  static SENSOR_DEVICE_ATTR_RW(auto_fan2_channel, fan_auto_channel, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  
  /* Auto Temps */
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
372
  static ssize_t auto_temp_off_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
373
  				  struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
375
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  	struct adm1031_data *data = adm1031_update_device(dev);
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
377
378
  	return sprintf(buf, "%d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
  		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
381
  static ssize_t auto_temp_min_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
382
  				  struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
384
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ",
  		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
  }
  static ssize_t
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
391
392
  auto_temp_min_store(struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
394
395
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
396
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
397
398
399
400
401
402
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403

145e74a4e   Guenter Roeck   hwmon: (adm1031) ...
404
  	val = clamp_val(val, 0, 127000);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
405
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
  	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
  	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
  			    data->auto_temp[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
409
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
412
  static ssize_t auto_temp_max_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
413
  				  struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
415
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
419
420
421
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ",
  		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
  }
  static ssize_t
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
422
423
  auto_temp_max_store(struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
425
426
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
427
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
428
429
430
431
432
433
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434

145e74a4e   Guenter Roeck   hwmon: (adm1031) ...
435
  	val = clamp_val(val, 0, 127000);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
436
  	mutex_lock(&data->update_lock);
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
437
438
  	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
  						  data->pwm[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
  			    data->temp_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
441
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
444
445
446
447
448
449
450
451
452
  static SENSOR_DEVICE_ATTR_RO(auto_temp1_off, auto_temp_off, 0);
  static SENSOR_DEVICE_ATTR_RW(auto_temp1_min, auto_temp_min, 0);
  static SENSOR_DEVICE_ATTR_RW(auto_temp1_max, auto_temp_max, 0);
  static SENSOR_DEVICE_ATTR_RO(auto_temp2_off, auto_temp_off, 1);
  static SENSOR_DEVICE_ATTR_RW(auto_temp2_min, auto_temp_min, 1);
  static SENSOR_DEVICE_ATTR_RW(auto_temp2_max, auto_temp_max, 1);
  static SENSOR_DEVICE_ATTR_RO(auto_temp3_off, auto_temp_off, 2);
  static SENSOR_DEVICE_ATTR_RW(auto_temp3_min, auto_temp_min, 2);
  static SENSOR_DEVICE_ATTR_RW(auto_temp3_max, auto_temp_max, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
  
  /* pwm */
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
455
456
  static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
  			char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
458
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", PWM_FROM_REG(data->pwm[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
463
464
  static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
  			 const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
466
467
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
468
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
469
470
471
472
473
474
  	long val;
  	int ret, reg;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
476
  	mutex_lock(&data->update_lock);
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
477
  	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
  	    (((val>>4) & 0xf) != 5)) {
  		/* In automatic mode, the only PWM accepted is 33% */
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
480
  		mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
  		return -EINVAL;
  	}
  	data->pwm[nr] = PWM_TO_REG(val);
  	reg = adm1031_read_value(client, ADM1031_REG_PWM);
  	adm1031_write_value(client, ADM1031_REG_PWM,
  			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
  			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
488
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
491
492
493
494
  static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
  static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
  static SENSOR_DEVICE_ATTR_RW(auto_fan1_min_pwm, pwm, 0);
  static SENSOR_DEVICE_ATTR_RW(auto_fan2_min_pwm, pwm, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
499
  
  /* Fans */
  
  /*
   * That function checks the cases where the fan reading is not
44bbe87e9   Steven Cole   [PATCH] Spelling ...
500
   * relevant.  It is used to provide 0 as fan reading when the fan is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
506
507
508
   * not supposed to run
   */
  static int trust_fan_readings(struct adm1031_data *data, int chan)
  {
  	int res = 0;
  
  	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
  		switch (data->conf1 & 0x60) {
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
509
510
511
512
513
  		case 0x00:
  			/*
  			 * remote temp1 controls fan1,
  			 * remote temp2 controls fan2
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  			res = data->temp[chan+1] >=
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
515
  			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  			break;
  		case 0x20:	/* remote temp1 controls both fans */
  			res =
  			    data->temp[1] >=
  			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
  			break;
  		case 0x40:	/* remote temp2 controls both fans */
  			res =
  			    data->temp[2] >=
  			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
  			break;
  		case 0x60:	/* max controls both fans */
  			res =
  			    data->temp[0] >=
  			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
  			    || data->temp[1] >=
  			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
533
  			    || (data->chip_type == adm1031
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
542
  				&& data->temp[2] >=
  				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
  			break;
  		}
  	} else {
  		res = data->pwm[chan] > 0;
  	}
  	return res;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
543
544
  static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
  			char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
546
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
553
554
  	struct adm1031_data *data = adm1031_update_device(dev);
  	int value;
  
  	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
  				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
  	return sprintf(buf, "%d
  ", value);
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
555
556
  static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
  			    char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
558
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
562
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN_DIV_FROM_REG(data->fan_div[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
563
564
  static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
  			    char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
566
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
572
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ",
  		       FAN_FROM_REG(data->fan_min[nr],
  				    FAN_DIV_FROM_REG(data->fan_div[nr])));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
573
574
575
  static ssize_t fan_min_store(struct device *dev,
  			     struct device_attribute *attr, const char *buf,
  			     size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
577
578
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
579
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
580
581
582
583
584
585
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
587
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  	if (val) {
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
589
  		data->fan_min[nr] =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
593
594
  			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
  	} else {
  		data->fan_min[nr] = 0xff;
  	}
  	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
595
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
598
599
600
  static ssize_t fan_div_store(struct device *dev,
  			     struct device_attribute *attr, const char *buf,
  			     size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
602
603
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
604
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
605
  	long val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
608
  	u8 tmp;
  	int old_div;
  	int new_min;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
609
610
611
612
613
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
  
  	tmp = val == 8 ? 0xc0 :
  	      val == 4 ? 0x80 :
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
617
618
  	      val == 2 ? 0x40 :
  	      val == 1 ? 0x00 :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
621
  	      0xff;
  	if (tmp == 0xff)
  		return -EINVAL;
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
622

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
623
  	mutex_lock(&data->update_lock);
38a1f0e9a   Jean Delvare   hwmon: (adm1031) ...
624
625
626
627
628
629
630
  	/* Get fresh readings */
  	data->fan_div[nr] = adm1031_read_value(client,
  					       ADM1031_REG_FAN_DIV(nr));
  	data->fan_min[nr] = adm1031_read_value(client,
  					       ADM1031_REG_FAN_MIN(nr));
  
  	/* Write the new clock divider and fan min */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
632
633
  	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
  	new_min = data->fan_min[nr] * old_div / val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635

6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
636
  	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  			    data->fan_div[nr]);
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
638
  	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  			    data->fan_min[nr]);
38a1f0e9a   Jean Delvare   hwmon: (adm1031) ...
640
641
642
  
  	/* Invalidate the cache: fan speed is no longer valid */
  	data->valid = 0;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
643
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
646
647
648
649
650
651
  static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
  static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
  static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
  static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
  static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
  static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
  
  /* Temps */
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
654
655
  static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
  			 char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
657
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
665
  	struct adm1031_data *data = adm1031_update_device(dev);
  	int ext;
  	ext = nr == 0 ?
  	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
  	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG_EXT(data->temp[nr], ext));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
666
  static ssize_t temp_offset_show(struct device *dev,
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
667
668
669
670
671
672
673
674
  				struct device_attribute *attr, char *buf)
  {
  	int nr = to_sensor_dev_attr(attr)->index;
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ",
  		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
675
  static ssize_t temp_min_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
676
  			     struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
678
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_min[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
683
  static ssize_t temp_max_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
684
  			     struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
686
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
689
690
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_max[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
691
  static ssize_t temp_crit_show(struct device *dev,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
692
  			      struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
694
  	int nr = to_sensor_dev_attr(attr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
697
698
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_crit[nr]));
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
699
700
701
  static ssize_t temp_offset_store(struct device *dev,
  				 struct device_attribute *attr,
  				 const char *buf, size_t count)
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
702
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
703
704
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
705
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
706
707
708
709
710
711
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
712

2a844c148   Guenter Roeck   hwmon: Replace SE...
713
  	val = clamp_val(val, -15000, 15000);
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
714
715
716
717
718
719
720
  	mutex_lock(&data->update_lock);
  	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
  	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
  			    data->temp_offset[nr]);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
721
722
723
  static ssize_t temp_min_store(struct device *dev,
  			      struct device_attribute *attr, const char *buf,
  			      size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
725
726
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
727
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
728
729
730
731
732
733
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734

145e74a4e   Guenter Roeck   hwmon: (adm1031) ...
735
  	val = clamp_val(val, -55000, 127000);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
736
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
739
  	data->temp_min[nr] = TEMP_TO_REG(val);
  	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
  			    data->temp_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
740
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
743
744
745
  static ssize_t temp_max_store(struct device *dev,
  			      struct device_attribute *attr, const char *buf,
  			      size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
747
748
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
749
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
750
751
752
753
754
755
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756

145e74a4e   Guenter Roeck   hwmon: (adm1031) ...
757
  	val = clamp_val(val, -55000, 127000);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
758
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
  	data->temp_max[nr] = TEMP_TO_REG(val);
  	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
  			    data->temp_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
762
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
765
766
767
  static ssize_t temp_crit_store(struct device *dev,
  			       struct device_attribute *attr, const char *buf,
  			       size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
769
770
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
c801082d7   Jean Delvare   hwmon: (adm1031) ...
771
  	int nr = to_sensor_dev_attr(attr)->index;
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
772
773
774
775
776
777
  	long val;
  	int ret;
  
  	ret = kstrtol(buf, 10, &val);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778

145e74a4e   Guenter Roeck   hwmon: (adm1031) ...
779
  	val = clamp_val(val, -55000, 127000);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
780
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
  	data->temp_crit[nr] = TEMP_TO_REG(val);
  	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
  			    data->temp_crit[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
784
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
  	return count;
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
  static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
  static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
  
  /* Alarms */
bfb6b1732   Julia Lawall   hwmon: (adm1031) ...
804
  static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
1c720093f   Guenter Roeck   hwmon: (adm1031) ...
805
  			   char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
  {
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", data->alarm);
  }
bfb6b1732   Julia Lawall   hwmon: (adm1031) ...
811
  static DEVICE_ATTR_RO(alarms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812

8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
813
814
  static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
  			  char *buf)
050ab8789   Jean Delvare   hwmon: (adm1031) ...
815
816
817
818
819
820
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct adm1031_data *data = adm1031_update_device(dev);
  	return sprintf(buf, "%d
  ", (data->alarm >> bitnr) & 1);
  }
8e757e15a   Guenter Roeck   hwmon: (adm1031) ...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 0);
  static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1);
  static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2);
  static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
  static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 4);
  static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 5);
  static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
  static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 7);
  static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 8);
  static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 9);
  static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 10);
  static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, alarm, 11);
  static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 12);
  static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 13);
  static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836

a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
837
838
  /* Update Interval */
  static const unsigned int update_intervals[] = {
87c33daad   Jean Delvare   hwmon: (adm1031) ...
839
840
  	16000, 8000, 4000, 2000, 1000, 500, 250, 125,
  };
bfb6b1732   Julia Lawall   hwmon: (adm1031) ...
841
  static ssize_t update_interval_show(struct device *dev,
a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
842
  				    struct device_attribute *attr, char *buf)
87c33daad   Jean Delvare   hwmon: (adm1031) ...
843
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
844
  	struct adm1031_data *data = dev_get_drvdata(dev);
87c33daad   Jean Delvare   hwmon: (adm1031) ...
845

a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
846
847
  	return sprintf(buf, "%u
  ", data->update_interval);
87c33daad   Jean Delvare   hwmon: (adm1031) ...
848
  }
bfb6b1732   Julia Lawall   hwmon: (adm1031) ...
849
850
851
  static ssize_t update_interval_store(struct device *dev,
  				     struct device_attribute *attr,
  				     const char *buf, size_t count)
87c33daad   Jean Delvare   hwmon: (adm1031) ...
852
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
853
854
  	struct adm1031_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
87c33daad   Jean Delvare   hwmon: (adm1031) ...
855
856
857
  	unsigned long val;
  	int i, err;
  	u8 reg;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
858
  	err = kstrtoul(buf, 10, &val);
87c33daad   Jean Delvare   hwmon: (adm1031) ...
859
860
  	if (err)
  		return err;
a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
861
862
863
864
865
866
  	/*
  	 * Find the nearest update interval from the table.
  	 * Use it to determine the matching update rate.
  	 */
  	for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
  		if (val >= update_intervals[i])
87c33daad   Jean Delvare   hwmon: (adm1031) ...
867
868
  			break;
  	}
a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
869
  	/* if not found, we point to the last entry (lowest update interval) */
87c33daad   Jean Delvare   hwmon: (adm1031) ...
870
871
872
873
874
875
876
877
  
  	/* set the new update rate while preserving other settings */
  	reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
  	reg &= ~ADM1031_UPDATE_RATE_MASK;
  	reg |= i << ADM1031_UPDATE_RATE_SHIFT;
  	adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
  
  	mutex_lock(&data->update_lock);
a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
878
  	data->update_interval = update_intervals[i];
87c33daad   Jean Delvare   hwmon: (adm1031) ...
879
880
881
882
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
bfb6b1732   Julia Lawall   hwmon: (adm1031) ...
883
  static DEVICE_ATTR_RW(update_interval);
87c33daad   Jean Delvare   hwmon: (adm1031) ...
884

681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
885
  static struct attribute *adm1031_attributes[] = {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
886
887
888
  	&sensor_dev_attr_fan1_input.dev_attr.attr,
  	&sensor_dev_attr_fan1_div.dev_attr.attr,
  	&sensor_dev_attr_fan1_min.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
889
890
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
  	&sensor_dev_attr_fan1_fault.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
891
892
893
  	&sensor_dev_attr_pwm1.dev_attr.attr,
  	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
894
  	&sensor_dev_attr_temp1_offset.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
895
  	&sensor_dev_attr_temp1_min.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
896
  	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
897
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
898
  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
899
  	&sensor_dev_attr_temp1_crit.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
900
  	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
901
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
902
  	&sensor_dev_attr_temp2_offset.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
903
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
904
  	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
905
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
906
  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
907
  	&sensor_dev_attr_temp2_crit.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
908
909
  	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
910
911
912
913
914
915
916
917
918
919
  
  	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
  	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
  	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
  
  	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
  	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
  	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
  
  	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
920

a51b9944a   Guenter Roeck   hwmon: (adm1031) ...
921
  	&dev_attr_update_interval.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
922
923
924
925
926
927
928
929
930
931
  	&dev_attr_alarms.attr,
  
  	NULL
  };
  
  static const struct attribute_group adm1031_group = {
  	.attrs = adm1031_attributes,
  };
  
  static struct attribute *adm1031_attributes_opt[] = {
c801082d7   Jean Delvare   hwmon: (adm1031) ...
932
933
934
  	&sensor_dev_attr_fan2_input.dev_attr.attr,
  	&sensor_dev_attr_fan2_div.dev_attr.attr,
  	&sensor_dev_attr_fan2_min.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
935
936
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
  	&sensor_dev_attr_fan2_fault.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
937
938
939
  	&sensor_dev_attr_pwm2.dev_attr.attr,
  	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
49dc9efed   Ira Snyder   hwmon: (adm1031) ...
940
  	&sensor_dev_attr_temp3_offset.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
941
  	&sensor_dev_attr_temp3_min.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
942
  	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
943
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
944
  	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
945
  	&sensor_dev_attr_temp3_crit.dev_attr.attr,
050ab8789   Jean Delvare   hwmon: (adm1031) ...
946
947
  	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_fault.dev_attr.attr,
c801082d7   Jean Delvare   hwmon: (adm1031) ...
948
949
950
951
  	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
  	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
  	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
952
953
954
955
956
957
  	NULL
  };
  
  static const struct attribute_group adm1031_group_opt = {
  	.attrs = adm1031_attributes_opt,
  };
af200f881   Jean Delvare   hwmon: (adm1031) ...
958
  /* Return 0 if detection is successful, -ENODEV otherwise */
310ec7921   Jean Delvare   i2c: Drop the kin...
959
  static int adm1031_detect(struct i2c_client *client,
af200f881   Jean Delvare   hwmon: (adm1031) ...
960
  			  struct i2c_board_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  {
af200f881   Jean Delvare   hwmon: (adm1031) ...
962
  	struct i2c_adapter *adapter = client->adapter;
52df6440a   Jean Delvare   hwmon: Clean up d...
963
964
  	const char *name;
  	int id, co;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
966
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
af200f881   Jean Delvare   hwmon: (adm1031) ...
967
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

52df6440a   Jean Delvare   hwmon: Clean up d...
969
970
  	id = i2c_smbus_read_byte_data(client, 0x3d);
  	co = i2c_smbus_read_byte_data(client, 0x3e);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971

52df6440a   Jean Delvare   hwmon: Clean up d...
972
973
974
  	if (!((id == 0x31 || id == 0x30) && co == 0x41))
  		return -ENODEV;
  	name = (id == 0x30) ? "adm1030" : "adm1031";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975

af200f881   Jean Delvare   hwmon: (adm1031) ...
976
  	strlcpy(info->type, name, I2C_NAME_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977

af200f881   Jean Delvare   hwmon: (adm1031) ...
978
979
  	return 0;
  }
278ee1c84   Axel Lin   hwmon: (adm1031) ...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  static void adm1031_init_client(struct i2c_client *client)
  {
  	unsigned int read_val;
  	unsigned int mask;
  	int i;
  	struct adm1031_data *data = i2c_get_clientdata(client);
  
  	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
  	if (data->chip_type == adm1031) {
  		mask |= (ADM1031_CONF2_PWM2_ENABLE |
  			ADM1031_CONF2_TACH2_ENABLE);
  	}
  	/* Initialize the ADM1031 chip (enables fan speed reading ) */
  	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
  	if ((read_val | mask) != read_val)
  		adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
  
  	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
  	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
  		adm1031_write_value(client, ADM1031_REG_CONF1,
  				    read_val | ADM1031_CONF1_MONITOR_ENABLE);
  	}
  
  	/* Read the chip's update rate */
  	mask = ADM1031_UPDATE_RATE_MASK;
  	read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
  	i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
  	/* Save it as update interval */
  	data->update_interval = update_intervals[i];
  }
674870385   Stephen Kitt   hwmon: use simple...
1010
1011
1012
  static const struct i2c_device_id adm1031_id[];
  
  static int adm1031_probe(struct i2c_client *client)
af200f881   Jean Delvare   hwmon: (adm1031) ...
1013
  {
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
1014
1015
  	struct device *dev = &client->dev;
  	struct device *hwmon_dev;
af200f881   Jean Delvare   hwmon: (adm1031) ...
1016
  	struct adm1031_data *data;
af200f881   Jean Delvare   hwmon: (adm1031) ...
1017

b060f3c4a   Axel Lin   hwmon: (adm1031) ...
1018
  	data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL);
dc2fd6632   Guenter Roeck   hwmon: (adm1031) ...
1019
1020
  	if (!data)
  		return -ENOMEM;
af200f881   Jean Delvare   hwmon: (adm1031) ...
1021
1022
  
  	i2c_set_clientdata(client, data);
b060f3c4a   Axel Lin   hwmon: (adm1031) ...
1023
  	data->client = client;
674870385   Stephen Kitt   hwmon: use simple...
1024
  	data->chip_type = i2c_match_id(adm1031_id, client)->driver_data;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1025
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026

af200f881   Jean Delvare   hwmon: (adm1031) ...
1027
1028
1029
1030
  	if (data->chip_type == adm1030)
  		data->chan_select_table = &auto_channel_select_table_adm1030;
  	else
  		data->chan_select_table = &auto_channel_select_table_adm1031;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
1032
  
  	/* Initialize the ADM1031 chip */
6d6006b8d   Jean Delvare   hwmon: (adm1031) ...
1033
  	adm1031_init_client(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034

b060f3c4a   Axel Lin   hwmon: (adm1031) ...
1035
1036
1037
1038
  	/* sysfs hooks */
  	data->groups[0] = &adm1031_group;
  	if (data->chip_type == adm1031)
  		data->groups[1] = &adm1031_group_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039

b060f3c4a   Axel Lin   hwmon: (adm1031) ...
1040
1041
1042
  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
  							   data, data->groups);
  	return PTR_ERR_OR_ZERO(hwmon_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
  }
278ee1c84   Axel Lin   hwmon: (adm1031) ...
1044
1045
1046
1047
1048
1049
  static const struct i2c_device_id adm1031_id[] = {
  	{ "adm1030", adm1030 },
  	{ "adm1031", adm1031 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, adm1031_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050

278ee1c84   Axel Lin   hwmon: (adm1031) ...
1051
1052
1053
1054
1055
  static struct i2c_driver adm1031_driver = {
  	.class		= I2C_CLASS_HWMON,
  	.driver = {
  		.name = "adm1031",
  	},
674870385   Stephen Kitt   hwmon: use simple...
1056
  	.probe_new	= adm1031_probe,
278ee1c84   Axel Lin   hwmon: (adm1031) ...
1057
1058
1059
1060
  	.id_table	= adm1031_id,
  	.detect		= adm1031_detect,
  	.address_list	= normal_i2c,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061

f0967eea8   Axel Lin   hwmon: convert dr...
1062
  module_i2c_driver(adm1031_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
1065
1066
  
  MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
  MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
  MODULE_LICENSE("GPL");