blob: 08bbeaf64e940810cb8e9bae6f4475d783f53122 [file] [log] [blame]
Jean Delvare08e7e272005-04-25 22:43:25 +02001/*
2 w83627ehf - Driver for the hardware monitoring functionality of
3 the Winbond W83627EHF Super-I/O chip
4 Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
5
6 Shamelessly ripped from the w83627hf driver
7 Copyright (C) 2003 Mark Studebaker
8
9 Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
10 in testing and debugging this driver.
11
Jean Delvare8dd2d2c2005-07-27 21:33:15 +020012 This driver also supports the W83627EHG, which is the lead-free
13 version of the W83627EHF.
14
Jean Delvare08e7e272005-04-25 22:43:25 +020015 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
29
30 Supports the following chips:
31
32 Chip #vin #fan #pwm #temp chip_id man_id
Rudolf Marekcf0676f2006-03-23 16:25:22 +010033 w83627ehf 10 5 - 3 0x88 0x5ca3
Jean Delvare08e7e272005-04-25 22:43:25 +020034*/
35
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/i2c.h>
Jean Delvarefde09502005-07-19 23:51:07 +020040#include <linux/i2c-isa.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040041#include <linux/hwmon.h>
Yuan Mu412fec82006-02-05 23:24:16 +010042#include <linux/hwmon-sysfs.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040043#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010044#include <linux/mutex.h>
Jean Delvare08e7e272005-04-25 22:43:25 +020045#include <asm/io.h>
46#include "lm75.h"
47
Jean Delvare2d8672c2005-07-19 23:56:35 +020048/* The actual ISA address is read from Super-I/O configuration space */
49static unsigned short address;
Jean Delvare08e7e272005-04-25 22:43:25 +020050
51/*
52 * Super-I/O constants and functions
53 */
54
55static int REG; /* The register to read/write */
56static int VAL; /* The value to read/write */
57
58#define W83627EHF_LD_HWM 0x0b
59
60#define SIO_REG_LDSEL 0x07 /* Logical device select */
61#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
62#define SIO_REG_ENABLE 0x30 /* Logical device enable */
63#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
64
65#define SIO_W83627EHF_ID 0x8840
66#define SIO_ID_MASK 0xFFC0
67
68static inline void
69superio_outb(int reg, int val)
70{
71 outb(reg, REG);
72 outb(val, VAL);
73}
74
75static inline int
76superio_inb(int reg)
77{
78 outb(reg, REG);
79 return inb(VAL);
80}
81
82static inline void
83superio_select(int ld)
84{
85 outb(SIO_REG_LDSEL, REG);
86 outb(ld, VAL);
87}
88
89static inline void
90superio_enter(void)
91{
92 outb(0x87, REG);
93 outb(0x87, REG);
94}
95
96static inline void
97superio_exit(void)
98{
99 outb(0x02, REG);
100 outb(0x02, VAL);
101}
102
103/*
104 * ISA constants
105 */
106
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200107#define REGION_ALIGNMENT ~7
108#define REGION_OFFSET 5
109#define REGION_LENGTH 2
Jean Delvare08e7e272005-04-25 22:43:25 +0200110#define ADDR_REG_OFFSET 5
111#define DATA_REG_OFFSET 6
112
113#define W83627EHF_REG_BANK 0x4E
114#define W83627EHF_REG_CONFIG 0x40
115#define W83627EHF_REG_CHIP_ID 0x49
116#define W83627EHF_REG_MAN_ID 0x4F
117
118static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
119static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
120
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100121/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
122#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
123 (0x554 + (((nr) - 7) * 2)))
124#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
125 (0x555 + (((nr) - 7) * 2)))
126#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
127 (0x550 + (nr) - 7))
128
Jean Delvare08e7e272005-04-25 22:43:25 +0200129#define W83627EHF_REG_TEMP1 0x27
130#define W83627EHF_REG_TEMP1_HYST 0x3a
131#define W83627EHF_REG_TEMP1_OVER 0x39
132static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
133static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
134static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
135static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
136
137/* Fan clock dividers are spread over the following five registers */
138#define W83627EHF_REG_FANDIV1 0x47
139#define W83627EHF_REG_FANDIV2 0x4B
140#define W83627EHF_REG_VBAT 0x5D
141#define W83627EHF_REG_DIODE 0x59
142#define W83627EHF_REG_SMI_OVT 0x4C
143
144/*
145 * Conversions
146 */
147
148static inline unsigned int
149fan_from_reg(u8 reg, unsigned int div)
150{
151 if (reg == 0 || reg == 255)
152 return 0;
153 return 1350000U / (reg * div);
154}
155
156static inline unsigned int
157div_from_reg(u8 reg)
158{
159 return 1 << reg;
160}
161
162static inline int
163temp1_from_reg(s8 reg)
164{
165 return reg * 1000;
166}
167
168static inline s8
169temp1_to_reg(int temp)
170{
171 if (temp <= -128000)
172 return -128;
173 if (temp >= 127000)
174 return 127;
175 if (temp < 0)
176 return (temp - 500) / 1000;
177 return (temp + 500) / 1000;
178}
179
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100180/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
181
182static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
183
184static inline long in_from_reg(u8 reg, u8 nr)
185{
186 return reg * scale_in[nr];
187}
188
189static inline u8 in_to_reg(u32 val, u8 nr)
190{
191 return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
192}
193
Jean Delvare08e7e272005-04-25 22:43:25 +0200194/*
195 * Data structures and manipulation thereof
196 */
197
198struct w83627ehf_data {
199 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400200 struct class_device *class_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100201 struct mutex lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200202
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100203 struct mutex update_lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200204 char valid; /* !=0 if following fields are valid */
205 unsigned long last_updated; /* In jiffies */
206
207 /* Register values */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100208 u8 in[10]; /* Register value */
209 u8 in_max[10]; /* Register value */
210 u8 in_min[10]; /* Register value */
Jean Delvare08e7e272005-04-25 22:43:25 +0200211 u8 fan[5];
212 u8 fan_min[5];
213 u8 fan_div[5];
214 u8 has_fan; /* some fan inputs can be disabled */
215 s8 temp1;
216 s8 temp1_max;
217 s8 temp1_max_hyst;
218 s16 temp[2];
219 s16 temp_max[2];
220 s16 temp_max_hyst[2];
221};
222
223static inline int is_word_sized(u16 reg)
224{
225 return (((reg & 0xff00) == 0x100
226 || (reg & 0xff00) == 0x200)
227 && ((reg & 0x00ff) == 0x50
228 || (reg & 0x00ff) == 0x53
229 || (reg & 0x00ff) == 0x55));
230}
231
232/* We assume that the default bank is 0, thus the following two functions do
233 nothing for registers which live in bank 0. For others, they respectively
234 set the bank register to the correct value (before the register is
235 accessed), and back to 0 (afterwards). */
236static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
237{
238 if (reg & 0xff00) {
239 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
240 outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
241 }
242}
243
244static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
245{
246 if (reg & 0xff00) {
247 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
248 outb_p(0, client->addr + DATA_REG_OFFSET);
249 }
250}
251
252static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
253{
254 struct w83627ehf_data *data = i2c_get_clientdata(client);
255 int res, word_sized = is_word_sized(reg);
256
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100257 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200258
259 w83627ehf_set_bank(client, reg);
260 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
261 res = inb_p(client->addr + DATA_REG_OFFSET);
262 if (word_sized) {
263 outb_p((reg & 0xff) + 1,
264 client->addr + ADDR_REG_OFFSET);
265 res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
266 }
267 w83627ehf_reset_bank(client, reg);
268
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100269 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200270
271 return res;
272}
273
274static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
275{
276 struct w83627ehf_data *data = i2c_get_clientdata(client);
277 int word_sized = is_word_sized(reg);
278
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100279 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200280
281 w83627ehf_set_bank(client, reg);
282 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
283 if (word_sized) {
284 outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
285 outb_p((reg & 0xff) + 1,
286 client->addr + ADDR_REG_OFFSET);
287 }
288 outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
289 w83627ehf_reset_bank(client, reg);
290
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100291 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200292 return 0;
293}
294
295/* This function assumes that the caller holds data->update_lock */
296static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
297{
298 struct w83627ehf_data *data = i2c_get_clientdata(client);
299 u8 reg;
300
301 switch (nr) {
302 case 0:
303 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
304 | ((data->fan_div[0] & 0x03) << 4);
305 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
306 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
307 | ((data->fan_div[0] & 0x04) << 3);
308 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
309 break;
310 case 1:
311 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
312 | ((data->fan_div[1] & 0x03) << 6);
313 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
314 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
315 | ((data->fan_div[1] & 0x04) << 4);
316 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
317 break;
318 case 2:
319 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
320 | ((data->fan_div[2] & 0x03) << 6);
321 w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
322 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
323 | ((data->fan_div[2] & 0x04) << 5);
324 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
325 break;
326 case 3:
327 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
328 | (data->fan_div[3] & 0x03);
329 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
330 reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
331 | ((data->fan_div[3] & 0x04) << 5);
332 w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
333 break;
334 case 4:
335 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
336 | ((data->fan_div[4] & 0x03) << 3)
337 | ((data->fan_div[4] & 0x04) << 5);
338 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
339 break;
340 }
341}
342
343static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
344{
345 struct i2c_client *client = to_i2c_client(dev);
346 struct w83627ehf_data *data = i2c_get_clientdata(client);
347 int i;
348
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100349 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200350
351 if (time_after(jiffies, data->last_updated + HZ)
352 || !data->valid) {
353 /* Fan clock dividers */
354 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
355 data->fan_div[0] = (i >> 4) & 0x03;
356 data->fan_div[1] = (i >> 6) & 0x03;
357 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
358 data->fan_div[2] = (i >> 6) & 0x03;
359 i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
360 data->fan_div[0] |= (i >> 3) & 0x04;
361 data->fan_div[1] |= (i >> 4) & 0x04;
362 data->fan_div[2] |= (i >> 5) & 0x04;
363 if (data->has_fan & ((1 << 3) | (1 << 4))) {
364 i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
365 data->fan_div[3] = i & 0x03;
366 data->fan_div[4] = ((i >> 2) & 0x03)
367 | ((i >> 5) & 0x04);
368 }
369 if (data->has_fan & (1 << 3)) {
370 i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
371 data->fan_div[3] |= (i >> 5) & 0x04;
372 }
373
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100374 /* Measured voltages and limits */
375 for (i = 0; i < 10; i++) {
376 data->in[i] = w83627ehf_read_value(client,
377 W83627EHF_REG_IN(i));
378 data->in_min[i] = w83627ehf_read_value(client,
379 W83627EHF_REG_IN_MIN(i));
380 data->in_max[i] = w83627ehf_read_value(client,
381 W83627EHF_REG_IN_MAX(i));
382 }
383
Jean Delvare08e7e272005-04-25 22:43:25 +0200384 /* Measured fan speeds and limits */
385 for (i = 0; i < 5; i++) {
386 if (!(data->has_fan & (1 << i)))
387 continue;
388
389 data->fan[i] = w83627ehf_read_value(client,
390 W83627EHF_REG_FAN[i]);
391 data->fan_min[i] = w83627ehf_read_value(client,
392 W83627EHF_REG_FAN_MIN[i]);
393
394 /* If we failed to measure the fan speed and clock
395 divider can be increased, let's try that for next
396 time */
397 if (data->fan[i] == 0xff
398 && data->fan_div[i] < 0x07) {
399 dev_dbg(&client->dev, "Increasing fan %d "
400 "clock divider from %u to %u\n",
401 i, div_from_reg(data->fan_div[i]),
402 div_from_reg(data->fan_div[i] + 1));
403 data->fan_div[i]++;
404 w83627ehf_write_fan_div(client, i);
405 /* Preserve min limit if possible */
406 if (data->fan_min[i] >= 2
407 && data->fan_min[i] != 255)
408 w83627ehf_write_value(client,
409 W83627EHF_REG_FAN_MIN[i],
410 (data->fan_min[i] /= 2));
411 }
412 }
413
414 /* Measured temperatures and limits */
415 data->temp1 = w83627ehf_read_value(client,
416 W83627EHF_REG_TEMP1);
417 data->temp1_max = w83627ehf_read_value(client,
418 W83627EHF_REG_TEMP1_OVER);
419 data->temp1_max_hyst = w83627ehf_read_value(client,
420 W83627EHF_REG_TEMP1_HYST);
421 for (i = 0; i < 2; i++) {
422 data->temp[i] = w83627ehf_read_value(client,
423 W83627EHF_REG_TEMP[i]);
424 data->temp_max[i] = w83627ehf_read_value(client,
425 W83627EHF_REG_TEMP_OVER[i]);
426 data->temp_max_hyst[i] = w83627ehf_read_value(client,
427 W83627EHF_REG_TEMP_HYST[i]);
428 }
429
430 data->last_updated = jiffies;
431 data->valid = 1;
432 }
433
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100434 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200435 return data;
436}
437
438/*
439 * Sysfs callback functions
440 */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100441#define show_in_reg(reg) \
442static ssize_t \
443show_##reg(struct device *dev, struct device_attribute *attr, \
444 char *buf) \
445{ \
446 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
447 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
448 int nr = sensor_attr->index; \
449 return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
450}
451show_in_reg(in)
452show_in_reg(in_min)
453show_in_reg(in_max)
454
455#define store_in_reg(REG, reg) \
456static ssize_t \
457store_in_##reg (struct device *dev, struct device_attribute *attr, \
458 const char *buf, size_t count) \
459{ \
460 struct i2c_client *client = to_i2c_client(dev); \
461 struct w83627ehf_data *data = i2c_get_clientdata(client); \
462 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
463 int nr = sensor_attr->index; \
464 u32 val = simple_strtoul(buf, NULL, 10); \
465 \
466 mutex_lock(&data->update_lock); \
467 data->in_##reg[nr] = in_to_reg(val, nr); \
468 w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
469 data->in_##reg[nr]); \
470 mutex_unlock(&data->update_lock); \
471 return count; \
472}
473
474store_in_reg(MIN, min)
475store_in_reg(MAX, max)
476
477static struct sensor_device_attribute sda_in_input[] = {
478 SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
479 SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
480 SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
481 SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
482 SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
483 SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
484 SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
485 SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
486 SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
487 SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
488};
489
490static struct sensor_device_attribute sda_in_min[] = {
491 SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
492 SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
493 SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
494 SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
495 SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
496 SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
497 SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
498 SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
499 SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
500 SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
501};
502
503static struct sensor_device_attribute sda_in_max[] = {
504 SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
505 SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
506 SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
507 SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
508 SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
509 SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
510 SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
511 SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
512 SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
513 SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
514};
515
516static void device_create_file_in(struct device *dev, int i)
517{
518 device_create_file(dev, &sda_in_input[i].dev_attr);
519 device_create_file(dev, &sda_in_min[i].dev_attr);
520 device_create_file(dev, &sda_in_max[i].dev_attr);
521}
Jean Delvare08e7e272005-04-25 22:43:25 +0200522
523#define show_fan_reg(reg) \
524static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100525show_##reg(struct device *dev, struct device_attribute *attr, \
526 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200527{ \
528 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100529 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
530 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200531 return sprintf(buf, "%d\n", \
532 fan_from_reg(data->reg[nr], \
533 div_from_reg(data->fan_div[nr]))); \
534}
535show_fan_reg(fan);
536show_fan_reg(fan_min);
537
538static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100539show_fan_div(struct device *dev, struct device_attribute *attr,
540 char *buf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200541{
542 struct w83627ehf_data *data = w83627ehf_update_device(dev);
Yuan Mu412fec82006-02-05 23:24:16 +0100543 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
544 int nr = sensor_attr->index;
545 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
Jean Delvare08e7e272005-04-25 22:43:25 +0200546}
547
548static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100549store_fan_min(struct device *dev, struct device_attribute *attr,
550 const char *buf, size_t count)
Jean Delvare08e7e272005-04-25 22:43:25 +0200551{
552 struct i2c_client *client = to_i2c_client(dev);
553 struct w83627ehf_data *data = i2c_get_clientdata(client);
Yuan Mu412fec82006-02-05 23:24:16 +0100554 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
555 int nr = sensor_attr->index;
Jean Delvare08e7e272005-04-25 22:43:25 +0200556 unsigned int val = simple_strtoul(buf, NULL, 10);
557 unsigned int reg;
558 u8 new_div;
559
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100560 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200561 if (!val) {
562 /* No min limit, alarm disabled */
563 data->fan_min[nr] = 255;
564 new_div = data->fan_div[nr]; /* No change */
565 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
566 } else if ((reg = 1350000U / val) >= 128 * 255) {
567 /* Speed below this value cannot possibly be represented,
568 even with the highest divider (128) */
569 data->fan_min[nr] = 254;
570 new_div = 7; /* 128 == (1 << 7) */
571 dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
572 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
573 } else if (!reg) {
574 /* Speed above this value cannot possibly be represented,
575 even with the lowest divider (1) */
576 data->fan_min[nr] = 1;
577 new_div = 0; /* 1 == (1 << 0) */
578 dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
Jean Delvareb9110b12005-05-02 23:08:22 +0200579 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
Jean Delvare08e7e272005-04-25 22:43:25 +0200580 } else {
581 /* Automatically pick the best divider, i.e. the one such
582 that the min limit will correspond to a register value
583 in the 96..192 range */
584 new_div = 0;
585 while (reg > 192 && new_div < 7) {
586 reg >>= 1;
587 new_div++;
588 }
589 data->fan_min[nr] = reg;
590 }
591
592 /* Write both the fan clock divider (if it changed) and the new
593 fan min (unconditionally) */
594 if (new_div != data->fan_div[nr]) {
595 if (new_div > data->fan_div[nr])
596 data->fan[nr] >>= (data->fan_div[nr] - new_div);
597 else
598 data->fan[nr] <<= (new_div - data->fan_div[nr]);
599
600 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
601 nr + 1, div_from_reg(data->fan_div[nr]),
602 div_from_reg(new_div));
603 data->fan_div[nr] = new_div;
604 w83627ehf_write_fan_div(client, nr);
605 }
606 w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
607 data->fan_min[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100608 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200609
610 return count;
611}
612
Yuan Mu412fec82006-02-05 23:24:16 +0100613static struct sensor_device_attribute sda_fan_input[] = {
614 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
615 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
616 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
617 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
618 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
619};
Jean Delvare08e7e272005-04-25 22:43:25 +0200620
Yuan Mu412fec82006-02-05 23:24:16 +0100621static struct sensor_device_attribute sda_fan_min[] = {
622 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
623 store_fan_min, 0),
624 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
625 store_fan_min, 1),
626 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
627 store_fan_min, 2),
628 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
629 store_fan_min, 3),
630 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
631 store_fan_min, 4),
632};
Jean Delvare08e7e272005-04-25 22:43:25 +0200633
Yuan Mu412fec82006-02-05 23:24:16 +0100634static struct sensor_device_attribute sda_fan_div[] = {
635 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
636 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
637 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
638 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
639 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
640};
Jean Delvare08e7e272005-04-25 22:43:25 +0200641
Yuan Mu412fec82006-02-05 23:24:16 +0100642static void device_create_file_fan(struct device *dev, int i)
643{
644 device_create_file(dev, &sda_fan_input[i].dev_attr);
645 device_create_file(dev, &sda_fan_div[i].dev_attr);
646 device_create_file(dev, &sda_fan_min[i].dev_attr);
647}
Jean Delvare08e7e272005-04-25 22:43:25 +0200648
649#define show_temp1_reg(reg) \
650static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700651show_##reg(struct device *dev, struct device_attribute *attr, \
652 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200653{ \
654 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
655 return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
656}
657show_temp1_reg(temp1);
658show_temp1_reg(temp1_max);
659show_temp1_reg(temp1_max_hyst);
660
661#define store_temp1_reg(REG, reg) \
662static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700663store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
664 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200665{ \
666 struct i2c_client *client = to_i2c_client(dev); \
667 struct w83627ehf_data *data = i2c_get_clientdata(client); \
668 u32 val = simple_strtoul(buf, NULL, 10); \
669 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100670 mutex_lock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200671 data->temp1_##reg = temp1_to_reg(val); \
672 w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
673 data->temp1_##reg); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100674 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200675 return count; \
676}
677store_temp1_reg(OVER, max);
678store_temp1_reg(HYST, max_hyst);
679
Jean Delvare08e7e272005-04-25 22:43:25 +0200680#define show_temp_reg(reg) \
681static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100682show_##reg(struct device *dev, struct device_attribute *attr, \
683 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200684{ \
685 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100686 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
687 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200688 return sprintf(buf, "%d\n", \
689 LM75_TEMP_FROM_REG(data->reg[nr])); \
690}
691show_temp_reg(temp);
692show_temp_reg(temp_max);
693show_temp_reg(temp_max_hyst);
694
695#define store_temp_reg(REG, reg) \
696static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100697store_##reg(struct device *dev, struct device_attribute *attr, \
698 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200699{ \
700 struct i2c_client *client = to_i2c_client(dev); \
701 struct w83627ehf_data *data = i2c_get_clientdata(client); \
Yuan Mu412fec82006-02-05 23:24:16 +0100702 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
703 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200704 u32 val = simple_strtoul(buf, NULL, 10); \
705 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100706 mutex_lock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200707 data->reg[nr] = LM75_TEMP_TO_REG(val); \
708 w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
709 data->reg[nr]); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100710 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200711 return count; \
712}
713store_temp_reg(OVER, temp_max);
714store_temp_reg(HYST, temp_max_hyst);
715
Yuan Mu412fec82006-02-05 23:24:16 +0100716static struct sensor_device_attribute sda_temp[] = {
717 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
718 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
719 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
720 SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
721 store_temp1_max, 0),
722 SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
723 store_temp_max, 0),
724 SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
725 store_temp_max, 1),
726 SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
727 store_temp1_max_hyst, 0),
728 SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
729 store_temp_max_hyst, 0),
730 SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
731 store_temp_max_hyst, 1),
732};
Jean Delvare08e7e272005-04-25 22:43:25 +0200733
734/*
735 * Driver and client management
736 */
737
738static struct i2c_driver w83627ehf_driver;
739
740static void w83627ehf_init_client(struct i2c_client *client)
741{
742 int i;
743 u8 tmp;
744
745 /* Start monitoring is needed */
746 tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
747 if (!(tmp & 0x01))
748 w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
749 tmp | 0x01);
750
751 /* Enable temp2 and temp3 if needed */
752 for (i = 0; i < 2; i++) {
753 tmp = w83627ehf_read_value(client,
754 W83627EHF_REG_TEMP_CONFIG[i]);
755 if (tmp & 0x01)
756 w83627ehf_write_value(client,
757 W83627EHF_REG_TEMP_CONFIG[i],
758 tmp & 0xfe);
759 }
760}
761
Jean Delvare2d8672c2005-07-19 23:56:35 +0200762static int w83627ehf_detect(struct i2c_adapter *adapter)
Jean Delvare08e7e272005-04-25 22:43:25 +0200763{
764 struct i2c_client *client;
765 struct w83627ehf_data *data;
Yuan Mu412fec82006-02-05 23:24:16 +0100766 struct device *dev;
Jean Delvare08e7e272005-04-25 22:43:25 +0200767 int i, err = 0;
768
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200769 if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100770 w83627ehf_driver.driver.name)) {
Jean Delvare08e7e272005-04-25 22:43:25 +0200771 err = -EBUSY;
772 goto exit;
773 }
774
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200775 if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
Jean Delvare08e7e272005-04-25 22:43:25 +0200776 err = -ENOMEM;
777 goto exit_release;
778 }
Jean Delvare08e7e272005-04-25 22:43:25 +0200779
780 client = &data->client;
781 i2c_set_clientdata(client, data);
782 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100783 mutex_init(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200784 client->adapter = adapter;
785 client->driver = &w83627ehf_driver;
786 client->flags = 0;
Yuan Mu412fec82006-02-05 23:24:16 +0100787 dev = &client->dev;
Jean Delvare08e7e272005-04-25 22:43:25 +0200788
789 strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
790 data->valid = 0;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100791 mutex_init(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200792
793 /* Tell the i2c layer a new client has arrived */
794 if ((err = i2c_attach_client(client)))
795 goto exit_free;
796
797 /* Initialize the chip */
798 w83627ehf_init_client(client);
799
800 /* A few vars need to be filled upon startup */
801 for (i = 0; i < 5; i++)
802 data->fan_min[i] = w83627ehf_read_value(client,
803 W83627EHF_REG_FAN_MIN[i]);
804
805 /* It looks like fan4 and fan5 pins can be alternatively used
806 as fan on/off switches */
807 data->has_fan = 0x07; /* fan1, fan2 and fan3 */
808 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
809 if (i & (1 << 2))
810 data->has_fan |= (1 << 3);
811 if (i & (1 << 0))
812 data->has_fan |= (1 << 4);
813
814 /* Register sysfs hooks */
Yuan Mu412fec82006-02-05 23:24:16 +0100815 data->class_dev = hwmon_device_register(dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400816 if (IS_ERR(data->class_dev)) {
817 err = PTR_ERR(data->class_dev);
818 goto exit_detach;
819 }
820
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100821 for (i = 0; i < 10; i++)
822 device_create_file_in(dev, i);
823
Yuan Mu412fec82006-02-05 23:24:16 +0100824 for (i = 0; i < 5; i++) {
825 if (data->has_fan & (1 << i))
826 device_create_file_fan(dev, i);
Jean Delvare08e7e272005-04-25 22:43:25 +0200827 }
Yuan Mu412fec82006-02-05 23:24:16 +0100828 for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
829 device_create_file(dev, &sda_temp[i].dev_attr);
Jean Delvare08e7e272005-04-25 22:43:25 +0200830
831 return 0;
832
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400833exit_detach:
834 i2c_detach_client(client);
Jean Delvare08e7e272005-04-25 22:43:25 +0200835exit_free:
836 kfree(data);
837exit_release:
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200838 release_region(address + REGION_OFFSET, REGION_LENGTH);
Jean Delvare08e7e272005-04-25 22:43:25 +0200839exit:
840 return err;
841}
842
Jean Delvare08e7e272005-04-25 22:43:25 +0200843static int w83627ehf_detach_client(struct i2c_client *client)
844{
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400845 struct w83627ehf_data *data = i2c_get_clientdata(client);
Jean Delvare08e7e272005-04-25 22:43:25 +0200846 int err;
847
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400848 hwmon_device_unregister(data->class_dev);
849
Jean Delvare7bef5592005-07-27 22:14:49 +0200850 if ((err = i2c_detach_client(client)))
Jean Delvare08e7e272005-04-25 22:43:25 +0200851 return err;
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200852 release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400853 kfree(data);
Jean Delvare08e7e272005-04-25 22:43:25 +0200854
855 return 0;
856}
857
858static struct i2c_driver w83627ehf_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100859 .driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100860 .name = "w83627ehf",
861 },
Jean Delvare2d8672c2005-07-19 23:56:35 +0200862 .attach_adapter = w83627ehf_detect,
Jean Delvare08e7e272005-04-25 22:43:25 +0200863 .detach_client = w83627ehf_detach_client,
864};
865
Jean Delvare2d8672c2005-07-19 23:56:35 +0200866static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
Jean Delvare08e7e272005-04-25 22:43:25 +0200867{
868 u16 val;
869
870 REG = sioaddr;
871 VAL = sioaddr + 1;
872 superio_enter();
873
874 val = (superio_inb(SIO_REG_DEVID) << 8)
875 | superio_inb(SIO_REG_DEVID + 1);
876 if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
877 superio_exit();
878 return -ENODEV;
879 }
880
881 superio_select(W83627EHF_LD_HWM);
882 val = (superio_inb(SIO_REG_ADDR) << 8)
883 | superio_inb(SIO_REG_ADDR + 1);
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200884 *addr = val & REGION_ALIGNMENT;
Jean Delvare2d8672c2005-07-19 23:56:35 +0200885 if (*addr == 0) {
Jean Delvare08e7e272005-04-25 22:43:25 +0200886 superio_exit();
887 return -ENODEV;
888 }
889
890 /* Activate logical device if needed */
891 val = superio_inb(SIO_REG_ENABLE);
892 if (!(val & 0x01))
893 superio_outb(SIO_REG_ENABLE, val | 0x01);
894
895 superio_exit();
896 return 0;
897}
898
899static int __init sensors_w83627ehf_init(void)
900{
Jean Delvare2d8672c2005-07-19 23:56:35 +0200901 if (w83627ehf_find(0x2e, &address)
902 && w83627ehf_find(0x4e, &address))
Jean Delvare08e7e272005-04-25 22:43:25 +0200903 return -ENODEV;
904
Jean Delvarefde09502005-07-19 23:51:07 +0200905 return i2c_isa_add_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +0200906}
907
908static void __exit sensors_w83627ehf_exit(void)
909{
Jean Delvarefde09502005-07-19 23:51:07 +0200910 i2c_isa_del_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +0200911}
912
913MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
914MODULE_DESCRIPTION("W83627EHF driver");
915MODULE_LICENSE("GPL");
916
917module_init(sensors_w83627ehf_init);
918module_exit(sensors_w83627ehf_exit);