aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2005-04-25 16:43:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-22 00:51:54 -0400
commit08e7e2789e0da49eadeb17121e24af22efeee84b (patch)
tree0e7edd2ffc4ad0a3b1e5c5fe070fb1bc460696cf /drivers/i2c/chips
parent40b5cda28aafe3744d8808c21f7959e472a9ecb1 (diff)
[PATCH] I2C: New hardware monitoring driver: w83627ehf
This is a new hardware monitoring driver, w83627ehf, which supports the Winbond W83627EHF Super-I/O chip. The driver is not complete, but already usable. It only implements fan speed and temperature monitoring, while the chip also supports voltage inputs with VID, PWM output and temperature sensor selection. I have no more time to work on this, but anyone with supported hardware could add the missing functionalities later. This driver is largely derived from the w83627hf driver. Thanks to Leon Moonen and Steve Cliffe for tesing the preliminary versions of my driver and reporting the problems they encountered. Thanks to Grant Coady for noticing and fixing various corner cases in the fan management. This third version of the driver hopefully addresses all the issues the original version had. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/i2c/chips')
-rw-r--r--drivers/i2c/chips/Kconfig14
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/w83627ehf.c839
3 files changed, 854 insertions, 0 deletions
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 3c8863f26c7e..ec52e3a399f3 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -384,6 +384,20 @@ config SENSORS_W83627HF
384 This driver can also be built as a module. If so, the module 384 This driver can also be built as a module. If so, the module
385 will be called w83627hf. 385 will be called w83627hf.
386 386
387config SENSORS_W83627EHF
388 tristate "Winbond W83627EHF"
389 depends on I2C && EXPERIMENTAL
390 select I2C_SENSOR
391 select I2C_ISA
392 help
393 If you say yes here you get preliminary support for the hardware
394 monitoring functionality of the Winbond W83627EHF Super-I/O chip.
395 Only fan and temperature inputs are supported at the moment, while
396 the chip does much more than that.
397
398 This driver can also be built as a module. If so, the module
399 will be called w83627ehf.
400
387endmenu 401endmenu
388 402
389menu "Other I2C Chip support" 403menu "Other I2C Chip support"
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 247fc982a6d2..2281435fc4c3 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
41obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o 41obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
42obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o 42obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
43obj-$(CONFIG_SENSORS_VIA686A) += via686a.o 43obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
44obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
44obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o 45obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
45obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o 46obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
46 47
diff --git a/drivers/i2c/chips/w83627ehf.c b/drivers/i2c/chips/w83627ehf.c
new file mode 100644
index 000000000000..7bb693d29784
--- /dev/null
+++ b/drivers/i2c/chips/w83627ehf.c
@@ -0,0 +1,839 @@
1/*
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
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26
27 Supports the following chips:
28
29 Chip #vin #fan #pwm #temp chip_id man_id
30 w83627ehf - 5 - 3 0x88 0x5ca3
31
32 This is a preliminary version of the driver, only supporting the
33 fan and temperature inputs. The chip does much more than that.
34*/
35
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/i2c.h>
40#include <linux/i2c-sensor.h>
41#include <asm/io.h>
42#include "lm75.h"
43
44/* Addresses to scan
45 The actual ISA address is read from Super-I/O configuration space */
46static unsigned short normal_i2c[] = { I2C_CLIENT_END };
47static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
48
49/* Insmod parameters */
50SENSORS_INSMOD_1(w83627ehf);
51
52/*
53 * Super-I/O constants and functions
54 */
55
56static int REG; /* The register to read/write */
57static int VAL; /* The value to read/write */
58
59#define W83627EHF_LD_HWM 0x0b
60
61#define SIO_REG_LDSEL 0x07 /* Logical device select */
62#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
63#define SIO_REG_ENABLE 0x30 /* Logical device enable */
64#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
65
66#define SIO_W83627EHF_ID 0x8840
67#define SIO_ID_MASK 0xFFC0
68
69static inline void
70superio_outb(int reg, int val)
71{
72 outb(reg, REG);
73 outb(val, VAL);
74}
75
76static inline int
77superio_inb(int reg)
78{
79 outb(reg, REG);
80 return inb(VAL);
81}
82
83static inline void
84superio_select(int ld)
85{
86 outb(SIO_REG_LDSEL, REG);
87 outb(ld, VAL);
88}
89
90static inline void
91superio_enter(void)
92{
93 outb(0x87, REG);
94 outb(0x87, REG);
95}
96
97static inline void
98superio_exit(void)
99{
100 outb(0x02, REG);
101 outb(0x02, VAL);
102}
103
104/*
105 * ISA constants
106 */
107
108#define REGION_LENGTH 8
109#define ADDR_REG_OFFSET 5
110#define DATA_REG_OFFSET 6
111
112#define W83627EHF_REG_BANK 0x4E
113#define W83627EHF_REG_CONFIG 0x40
114#define W83627EHF_REG_CHIP_ID 0x49
115#define W83627EHF_REG_MAN_ID 0x4F
116
117static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
118static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
119
120#define W83627EHF_REG_TEMP1 0x27
121#define W83627EHF_REG_TEMP1_HYST 0x3a
122#define W83627EHF_REG_TEMP1_OVER 0x39
123static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
124static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
125static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
126static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
127
128/* Fan clock dividers are spread over the following five registers */
129#define W83627EHF_REG_FANDIV1 0x47
130#define W83627EHF_REG_FANDIV2 0x4B
131#define W83627EHF_REG_VBAT 0x5D
132#define W83627EHF_REG_DIODE 0x59
133#define W83627EHF_REG_SMI_OVT 0x4C
134
135/*
136 * Conversions
137 */
138
139static inline unsigned int
140fan_from_reg(u8 reg, unsigned int div)
141{
142 if (reg == 0 || reg == 255)
143 return 0;
144 return 1350000U / (reg * div);
145}
146
147static inline unsigned int
148div_from_reg(u8 reg)
149{
150 return 1 << reg;
151}
152
153static inline int
154temp1_from_reg(s8 reg)
155{
156 return reg * 1000;
157}
158
159static inline s8
160temp1_to_reg(int temp)
161{
162 if (temp <= -128000)
163 return -128;
164 if (temp >= 127000)
165 return 127;
166 if (temp < 0)
167 return (temp - 500) / 1000;
168 return (temp + 500) / 1000;
169}
170
171/*
172 * Data structures and manipulation thereof
173 */
174
175struct w83627ehf_data {
176 struct i2c_client client;
177 struct semaphore lock;
178
179 struct semaphore update_lock;
180 char valid; /* !=0 if following fields are valid */
181 unsigned long last_updated; /* In jiffies */
182
183 /* Register values */
184 u8 fan[5];
185 u8 fan_min[5];
186 u8 fan_div[5];
187 u8 has_fan; /* some fan inputs can be disabled */
188 s8 temp1;
189 s8 temp1_max;
190 s8 temp1_max_hyst;
191 s16 temp[2];
192 s16 temp_max[2];
193 s16 temp_max_hyst[2];
194};
195
196static inline int is_word_sized(u16 reg)
197{
198 return (((reg & 0xff00) == 0x100
199 || (reg & 0xff00) == 0x200)
200 && ((reg & 0x00ff) == 0x50
201 || (reg & 0x00ff) == 0x53
202 || (reg & 0x00ff) == 0x55));
203}
204
205/* We assume that the default bank is 0, thus the following two functions do
206 nothing for registers which live in bank 0. For others, they respectively
207 set the bank register to the correct value (before the register is
208 accessed), and back to 0 (afterwards). */
209static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
210{
211 if (reg & 0xff00) {
212 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
213 outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
214 }
215}
216
217static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
218{
219 if (reg & 0xff00) {
220 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
221 outb_p(0, client->addr + DATA_REG_OFFSET);
222 }
223}
224
225static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
226{
227 struct w83627ehf_data *data = i2c_get_clientdata(client);
228 int res, word_sized = is_word_sized(reg);
229
230 down(&data->lock);
231
232 w83627ehf_set_bank(client, reg);
233 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
234 res = inb_p(client->addr + DATA_REG_OFFSET);
235 if (word_sized) {
236 outb_p((reg & 0xff) + 1,
237 client->addr + ADDR_REG_OFFSET);
238 res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
239 }
240 w83627ehf_reset_bank(client, reg);
241
242 up(&data->lock);
243
244 return res;
245}
246
247static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
248{
249 struct w83627ehf_data *data = i2c_get_clientdata(client);
250 int word_sized = is_word_sized(reg);
251
252 down(&data->lock);
253
254 w83627ehf_set_bank(client, reg);
255 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
256 if (word_sized) {
257 outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
258 outb_p((reg & 0xff) + 1,
259 client->addr + ADDR_REG_OFFSET);
260 }
261 outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
262 w83627ehf_reset_bank(client, reg);
263
264 up(&data->lock);
265 return 0;
266}
267
268/* This function assumes that the caller holds data->update_lock */
269static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
270{
271 struct w83627ehf_data *data = i2c_get_clientdata(client);
272 u8 reg;
273
274 switch (nr) {
275 case 0:
276 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
277 | ((data->fan_div[0] & 0x03) << 4);
278 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
279 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
280 | ((data->fan_div[0] & 0x04) << 3);
281 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
282 break;
283 case 1:
284 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
285 | ((data->fan_div[1] & 0x03) << 6);
286 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
287 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
288 | ((data->fan_div[1] & 0x04) << 4);
289 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
290 break;
291 case 2:
292 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
293 | ((data->fan_div[2] & 0x03) << 6);
294 w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
295 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
296 | ((data->fan_div[2] & 0x04) << 5);
297 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
298 break;
299 case 3:
300 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
301 | (data->fan_div[3] & 0x03);
302 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
303 reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
304 | ((data->fan_div[3] & 0x04) << 5);
305 w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
306 break;
307 case 4:
308 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
309 | ((data->fan_div[4] & 0x03) << 3)
310 | ((data->fan_div[4] & 0x04) << 5);
311 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
312 break;
313 }
314}
315
316static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
317{
318 struct i2c_client *client = to_i2c_client(dev);
319 struct w83627ehf_data *data = i2c_get_clientdata(client);
320 int i;
321
322 down(&data->update_lock);
323
324 if (time_after(jiffies, data->last_updated + HZ)
325 || !data->valid) {
326 /* Fan clock dividers */
327 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
328 data->fan_div[0] = (i >> 4) & 0x03;
329 data->fan_div[1] = (i >> 6) & 0x03;
330 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
331 data->fan_div[2] = (i >> 6) & 0x03;
332 i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
333 data->fan_div[0] |= (i >> 3) & 0x04;
334 data->fan_div[1] |= (i >> 4) & 0x04;
335 data->fan_div[2] |= (i >> 5) & 0x04;
336 if (data->has_fan & ((1 << 3) | (1 << 4))) {
337 i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
338 data->fan_div[3] = i & 0x03;
339 data->fan_div[4] = ((i >> 2) & 0x03)
340 | ((i >> 5) & 0x04);
341 }
342 if (data->has_fan & (1 << 3)) {
343 i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
344 data->fan_div[3] |= (i >> 5) & 0x04;
345 }
346
347 /* Measured fan speeds and limits */
348 for (i = 0; i < 5; i++) {
349 if (!(data->has_fan & (1 << i)))
350 continue;
351
352 data->fan[i] = w83627ehf_read_value(client,
353 W83627EHF_REG_FAN[i]);
354 data->fan_min[i] = w83627ehf_read_value(client,
355 W83627EHF_REG_FAN_MIN[i]);
356
357 /* If we failed to measure the fan speed and clock
358 divider can be increased, let's try that for next
359 time */
360 if (data->fan[i] == 0xff
361 && data->fan_div[i] < 0x07) {
362 dev_dbg(&client->dev, "Increasing fan %d "
363 "clock divider from %u to %u\n",
364 i, div_from_reg(data->fan_div[i]),
365 div_from_reg(data->fan_div[i] + 1));
366 data->fan_div[i]++;
367 w83627ehf_write_fan_div(client, i);
368 /* Preserve min limit if possible */
369 if (data->fan_min[i] >= 2
370 && data->fan_min[i] != 255)
371 w83627ehf_write_value(client,
372 W83627EHF_REG_FAN_MIN[i],
373 (data->fan_min[i] /= 2));
374 }
375 }
376
377 /* Measured temperatures and limits */
378 data->temp1 = w83627ehf_read_value(client,
379 W83627EHF_REG_TEMP1);
380 data->temp1_max = w83627ehf_read_value(client,
381 W83627EHF_REG_TEMP1_OVER);
382 data->temp1_max_hyst = w83627ehf_read_value(client,
383 W83627EHF_REG_TEMP1_HYST);
384 for (i = 0; i < 2; i++) {
385 data->temp[i] = w83627ehf_read_value(client,
386 W83627EHF_REG_TEMP[i]);
387 data->temp_max[i] = w83627ehf_read_value(client,
388 W83627EHF_REG_TEMP_OVER[i]);
389 data->temp_max_hyst[i] = w83627ehf_read_value(client,
390 W83627EHF_REG_TEMP_HYST[i]);
391 }
392
393 data->last_updated = jiffies;
394 data->valid = 1;
395 }
396
397 up(&data->update_lock);
398 return data;
399}
400
401/*
402 * Sysfs callback functions
403 */
404
405#define show_fan_reg(reg) \
406static ssize_t \
407show_##reg(struct device *dev, char *buf, int nr) \
408{ \
409 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
410 return sprintf(buf, "%d\n", \
411 fan_from_reg(data->reg[nr], \
412 div_from_reg(data->fan_div[nr]))); \
413}
414show_fan_reg(fan);
415show_fan_reg(fan_min);
416
417static ssize_t
418show_fan_div(struct device *dev, char *buf, int nr)
419{
420 struct w83627ehf_data *data = w83627ehf_update_device(dev);
421 return sprintf(buf, "%u\n",
422 div_from_reg(data->fan_div[nr]));
423}
424
425static ssize_t
426store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
427{
428 struct i2c_client *client = to_i2c_client(dev);
429 struct w83627ehf_data *data = i2c_get_clientdata(client);
430 unsigned int val = simple_strtoul(buf, NULL, 10);
431 unsigned int reg;
432 u8 new_div;
433
434 down(&data->update_lock);
435 if (!val) {
436 /* No min limit, alarm disabled */
437 data->fan_min[nr] = 255;
438 new_div = data->fan_div[nr]; /* No change */
439 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
440 } else if ((reg = 1350000U / val) >= 128 * 255) {
441 /* Speed below this value cannot possibly be represented,
442 even with the highest divider (128) */
443 data->fan_min[nr] = 254;
444 new_div = 7; /* 128 == (1 << 7) */
445 dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
446 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
447 } else if (!reg) {
448 /* Speed above this value cannot possibly be represented,
449 even with the lowest divider (1) */
450 data->fan_min[nr] = 1;
451 new_div = 0; /* 1 == (1 << 0) */
452 dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
453 "maximum\n", nr + 1, val, fan_from_reg(1, 0));
454 } else {
455 /* Automatically pick the best divider, i.e. the one such
456 that the min limit will correspond to a register value
457 in the 96..192 range */
458 new_div = 0;
459 while (reg > 192 && new_div < 7) {
460 reg >>= 1;
461 new_div++;
462 }
463 data->fan_min[nr] = reg;
464 }
465
466 /* Write both the fan clock divider (if it changed) and the new
467 fan min (unconditionally) */
468 if (new_div != data->fan_div[nr]) {
469 if (new_div > data->fan_div[nr])
470 data->fan[nr] >>= (data->fan_div[nr] - new_div);
471 else
472 data->fan[nr] <<= (new_div - data->fan_div[nr]);
473
474 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
475 nr + 1, div_from_reg(data->fan_div[nr]),
476 div_from_reg(new_div));
477 data->fan_div[nr] = new_div;
478 w83627ehf_write_fan_div(client, nr);
479 }
480 w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
481 data->fan_min[nr]);
482 up(&data->update_lock);
483
484 return count;
485}
486
487#define sysfs_fan_offset(offset) \
488static ssize_t \
489show_reg_fan_##offset(struct device *dev, char *buf) \
490{ \
491 return show_fan(dev, buf, offset-1); \
492} \
493static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
494 show_reg_fan_##offset, NULL);
495
496#define sysfs_fan_min_offset(offset) \
497static ssize_t \
498show_reg_fan##offset##_min(struct device *dev, char *buf) \
499{ \
500 return show_fan_min(dev, buf, offset-1); \
501} \
502static ssize_t \
503store_reg_fan##offset##_min(struct device *dev, const char *buf, \
504 size_t count) \
505{ \
506 return store_fan_min(dev, buf, count, offset-1); \
507} \
508static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
509 show_reg_fan##offset##_min, \
510 store_reg_fan##offset##_min);
511
512#define sysfs_fan_div_offset(offset) \
513static ssize_t \
514show_reg_fan##offset##_div(struct device *dev, char *buf) \
515{ \
516 return show_fan_div(dev, buf, offset - 1); \
517} \
518static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
519 show_reg_fan##offset##_div, NULL);
520
521sysfs_fan_offset(1);
522sysfs_fan_min_offset(1);
523sysfs_fan_div_offset(1);
524sysfs_fan_offset(2);
525sysfs_fan_min_offset(2);
526sysfs_fan_div_offset(2);
527sysfs_fan_offset(3);
528sysfs_fan_min_offset(3);
529sysfs_fan_div_offset(3);
530sysfs_fan_offset(4);
531sysfs_fan_min_offset(4);
532sysfs_fan_div_offset(4);
533sysfs_fan_offset(5);
534sysfs_fan_min_offset(5);
535sysfs_fan_div_offset(5);
536
537#define show_temp1_reg(reg) \
538static ssize_t \
539show_##reg(struct device *dev, char *buf) \
540{ \
541 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
542 return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
543}
544show_temp1_reg(temp1);
545show_temp1_reg(temp1_max);
546show_temp1_reg(temp1_max_hyst);
547
548#define store_temp1_reg(REG, reg) \
549static ssize_t \
550store_temp1_##reg(struct device *dev, const char *buf, size_t count) \
551{ \
552 struct i2c_client *client = to_i2c_client(dev); \
553 struct w83627ehf_data *data = i2c_get_clientdata(client); \
554 u32 val = simple_strtoul(buf, NULL, 10); \
555 \
556 down(&data->update_lock); \
557 data->temp1_##reg = temp1_to_reg(val); \
558 w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
559 data->temp1_##reg); \
560 up(&data->update_lock); \
561 return count; \
562}
563store_temp1_reg(OVER, max);
564store_temp1_reg(HYST, max_hyst);
565
566static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
567static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR,
568 show_temp1_max, store_temp1_max);
569static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR,
570 show_temp1_max_hyst, store_temp1_max_hyst);
571
572#define show_temp_reg(reg) \
573static ssize_t \
574show_##reg (struct device *dev, char *buf, int nr) \
575{ \
576 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
577 return sprintf(buf, "%d\n", \
578 LM75_TEMP_FROM_REG(data->reg[nr])); \
579}
580show_temp_reg(temp);
581show_temp_reg(temp_max);
582show_temp_reg(temp_max_hyst);
583
584#define store_temp_reg(REG, reg) \
585static ssize_t \
586store_##reg (struct device *dev, const char *buf, size_t count, int nr) \
587{ \
588 struct i2c_client *client = to_i2c_client(dev); \
589 struct w83627ehf_data *data = i2c_get_clientdata(client); \
590 u32 val = simple_strtoul(buf, NULL, 10); \
591 \
592 down(&data->update_lock); \
593 data->reg[nr] = LM75_TEMP_TO_REG(val); \
594 w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
595 data->reg[nr]); \
596 up(&data->update_lock); \
597 return count; \
598}
599store_temp_reg(OVER, temp_max);
600store_temp_reg(HYST, temp_max_hyst);
601
602#define sysfs_temp_offset(offset) \
603static ssize_t \
604show_reg_temp##offset (struct device *dev, char *buf) \
605{ \
606 return show_temp(dev, buf, offset - 2); \
607} \
608static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
609 show_reg_temp##offset, NULL);
610
611#define sysfs_temp_reg_offset(reg, offset) \
612static ssize_t \
613show_reg_temp##offset##_##reg(struct device *dev, char *buf) \
614{ \
615 return show_temp_##reg(dev, buf, offset - 2); \
616} \
617static ssize_t \
618store_reg_temp##offset##_##reg(struct device *dev, const char *buf, \
619 size_t count) \
620{ \
621 return store_temp_##reg(dev, buf, count, offset - 2); \
622} \
623static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
624 show_reg_temp##offset##_##reg, \
625 store_reg_temp##offset##_##reg);
626
627sysfs_temp_offset(2);
628sysfs_temp_reg_offset(max, 2);
629sysfs_temp_reg_offset(max_hyst, 2);
630sysfs_temp_offset(3);
631sysfs_temp_reg_offset(max, 3);
632sysfs_temp_reg_offset(max_hyst, 3);
633
634/*
635 * Driver and client management
636 */
637
638static struct i2c_driver w83627ehf_driver;
639
640static void w83627ehf_init_client(struct i2c_client *client)
641{
642 int i;
643 u8 tmp;
644
645 /* Start monitoring is needed */
646 tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
647 if (!(tmp & 0x01))
648 w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
649 tmp | 0x01);
650
651 /* Enable temp2 and temp3 if needed */
652 for (i = 0; i < 2; i++) {
653 tmp = w83627ehf_read_value(client,
654 W83627EHF_REG_TEMP_CONFIG[i]);
655 if (tmp & 0x01)
656 w83627ehf_write_value(client,
657 W83627EHF_REG_TEMP_CONFIG[i],
658 tmp & 0xfe);
659 }
660}
661
662static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
663{
664 struct i2c_client *client;
665 struct w83627ehf_data *data;
666 int i, err = 0;
667
668 if (!i2c_is_isa_adapter(adapter))
669 return 0;
670
671 if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
672 err = -EBUSY;
673 goto exit;
674 }
675
676 if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
677 err = -ENOMEM;
678 goto exit_release;
679 }
680 memset(data, 0, sizeof(struct w83627ehf_data));
681
682 client = &data->client;
683 i2c_set_clientdata(client, data);
684 client->addr = address;
685 init_MUTEX(&data->lock);
686 client->adapter = adapter;
687 client->driver = &w83627ehf_driver;
688 client->flags = 0;
689
690 strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
691 data->valid = 0;
692 init_MUTEX(&data->update_lock);
693
694 /* Tell the i2c layer a new client has arrived */
695 if ((err = i2c_attach_client(client)))
696 goto exit_free;
697
698 /* Initialize the chip */
699 w83627ehf_init_client(client);
700
701 /* A few vars need to be filled upon startup */
702 for (i = 0; i < 5; i++)
703 data->fan_min[i] = w83627ehf_read_value(client,
704 W83627EHF_REG_FAN_MIN[i]);
705
706 /* It looks like fan4 and fan5 pins can be alternatively used
707 as fan on/off switches */
708 data->has_fan = 0x07; /* fan1, fan2 and fan3 */
709 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
710 if (i & (1 << 2))
711 data->has_fan |= (1 << 3);
712 if (i & (1 << 0))
713 data->has_fan |= (1 << 4);
714
715 /* Register sysfs hooks */
716 device_create_file(&client->dev, &dev_attr_fan1_input);
717 device_create_file(&client->dev, &dev_attr_fan1_min);
718 device_create_file(&client->dev, &dev_attr_fan1_div);
719 device_create_file(&client->dev, &dev_attr_fan2_input);
720 device_create_file(&client->dev, &dev_attr_fan2_min);
721 device_create_file(&client->dev, &dev_attr_fan2_div);
722 device_create_file(&client->dev, &dev_attr_fan3_input);
723 device_create_file(&client->dev, &dev_attr_fan3_min);
724 device_create_file(&client->dev, &dev_attr_fan3_div);
725
726 if (data->has_fan & (1 << 3)) {
727 device_create_file(&client->dev, &dev_attr_fan4_input);
728 device_create_file(&client->dev, &dev_attr_fan4_min);
729 device_create_file(&client->dev, &dev_attr_fan4_div);
730 }
731 if (data->has_fan & (1 << 4)) {
732 device_create_file(&client->dev, &dev_attr_fan5_input);
733 device_create_file(&client->dev, &dev_attr_fan5_min);
734 device_create_file(&client->dev, &dev_attr_fan5_div);
735 }
736
737 device_create_file(&client->dev, &dev_attr_temp1_input);
738 device_create_file(&client->dev, &dev_attr_temp1_max);
739 device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
740 device_create_file(&client->dev, &dev_attr_temp2_input);
741 device_create_file(&client->dev, &dev_attr_temp2_max);
742 device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
743 device_create_file(&client->dev, &dev_attr_temp3_input);
744 device_create_file(&client->dev, &dev_attr_temp3_max);
745 device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
746
747 return 0;
748
749exit_free:
750 kfree(data);
751exit_release:
752 release_region(address, REGION_LENGTH);
753exit:
754 return err;
755}
756
757static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
758{
759 if (!(adapter->class & I2C_CLASS_HWMON))
760 return 0;
761 return i2c_detect(adapter, &addr_data, w83627ehf_detect);
762}
763
764static int w83627ehf_detach_client(struct i2c_client *client)
765{
766 int err;
767
768 if ((err = i2c_detach_client(client))) {
769 dev_err(&client->dev, "Client deregistration failed, "
770 "client not detached.\n");
771 return err;
772 }
773 release_region(client->addr, REGION_LENGTH);
774 kfree(i2c_get_clientdata(client));
775
776 return 0;
777}
778
779static struct i2c_driver w83627ehf_driver = {
780 .owner = THIS_MODULE,
781 .name = "w83627ehf",
782 .flags = I2C_DF_NOTIFY,
783 .attach_adapter = w83627ehf_attach_adapter,
784 .detach_client = w83627ehf_detach_client,
785};
786
787static int __init w83627ehf_find(int sioaddr, int *address)
788{
789 u16 val;
790
791 REG = sioaddr;
792 VAL = sioaddr + 1;
793 superio_enter();
794
795 val = (superio_inb(SIO_REG_DEVID) << 8)
796 | superio_inb(SIO_REG_DEVID + 1);
797 if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
798 superio_exit();
799 return -ENODEV;
800 }
801
802 superio_select(W83627EHF_LD_HWM);
803 val = (superio_inb(SIO_REG_ADDR) << 8)
804 | superio_inb(SIO_REG_ADDR + 1);
805 *address = val & ~(REGION_LENGTH - 1);
806 if (*address == 0) {
807 superio_exit();
808 return -ENODEV;
809 }
810
811 /* Activate logical device if needed */
812 val = superio_inb(SIO_REG_ENABLE);
813 if (!(val & 0x01))
814 superio_outb(SIO_REG_ENABLE, val | 0x01);
815
816 superio_exit();
817 return 0;
818}
819
820static int __init sensors_w83627ehf_init(void)
821{
822 if (w83627ehf_find(0x2e, &normal_isa[0])
823 && w83627ehf_find(0x4e, &normal_isa[0]))
824 return -ENODEV;
825
826 return i2c_add_driver(&w83627ehf_driver);
827}
828
829static void __exit sensors_w83627ehf_exit(void)
830{
831 i2c_del_driver(&w83627ehf_driver);
832}
833
834MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
835MODULE_DESCRIPTION("W83627EHF driver");
836MODULE_LICENSE("GPL");
837
838module_init(sensors_w83627ehf_init);
839module_exit(sensors_w83627ehf_exit);