blob: 212a1558c63b62a0556f469f1370341e9c14b039 [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>
Jean Delvare3379cee2006-09-24 21:25:52 +02005 Copyright (C) 2006 Yuan Mu (Winbond),
Jean Delvare7188cc62006-12-12 18:18:30 +01006 Rudolf Marek <r.marek@assembler.cz>
David Hubbardc18beb52006-09-24 21:04:38 +02007 David Hubbard <david.c.hubbard@gmail.com>
Jean Delvare08e7e272005-04-25 22:43:25 +02008
9 Shamelessly ripped from the w83627hf driver
10 Copyright (C) 2003 Mark Studebaker
11
12 Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
13 in testing and debugging this driver.
14
Jean Delvare8dd2d2c2005-07-27 21:33:15 +020015 This driver also supports the W83627EHG, which is the lead-free
16 version of the W83627EHF.
17
Jean Delvare08e7e272005-04-25 22:43:25 +020018 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
22
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
32
33 Supports the following chips:
34
Rudolf Marek08c79952006-07-05 18:14:31 +020035 Chip #vin #fan #pwm #temp chip_id man_id
36 w83627ehf 10 5 4 3 0x88,0xa1 0x5ca3
Jean Delvare08e7e272005-04-25 22:43:25 +020037*/
38
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/slab.h>
42#include <linux/i2c.h>
Jean Delvarefde09502005-07-19 23:51:07 +020043#include <linux/i2c-isa.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040044#include <linux/hwmon.h>
Yuan Mu412fec82006-02-05 23:24:16 +010045#include <linux/hwmon-sysfs.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040046#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010047#include <linux/mutex.h>
Jean Delvare08e7e272005-04-25 22:43:25 +020048#include <asm/io.h>
49#include "lm75.h"
50
Jean Delvare2d8672c2005-07-19 23:56:35 +020051/* The actual ISA address is read from Super-I/O configuration space */
52static unsigned short address;
Jean Delvare08e7e272005-04-25 22:43:25 +020053
54/*
55 * Super-I/O constants and functions
56 */
57
58static int REG; /* The register to read/write */
59static int VAL; /* The value to read/write */
60
61#define W83627EHF_LD_HWM 0x0b
62
63#define SIO_REG_LDSEL 0x07 /* Logical device select */
64#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
65#define SIO_REG_ENABLE 0x30 /* Logical device enable */
66#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
67
68#define SIO_W83627EHF_ID 0x8840
69#define SIO_ID_MASK 0xFFC0
70
71static inline void
72superio_outb(int reg, int val)
73{
74 outb(reg, REG);
75 outb(val, VAL);
76}
77
78static inline int
79superio_inb(int reg)
80{
81 outb(reg, REG);
82 return inb(VAL);
83}
84
85static inline void
86superio_select(int ld)
87{
88 outb(SIO_REG_LDSEL, REG);
89 outb(ld, VAL);
90}
91
92static inline void
93superio_enter(void)
94{
95 outb(0x87, REG);
96 outb(0x87, REG);
97}
98
99static inline void
100superio_exit(void)
101{
102 outb(0x02, REG);
103 outb(0x02, VAL);
104}
105
106/*
107 * ISA constants
108 */
109
Petr Vandrovecada0c2f2005-10-07 23:11:03 +0200110#define REGION_ALIGNMENT ~7
111#define REGION_OFFSET 5
112#define REGION_LENGTH 2
Jean Delvare08e7e272005-04-25 22:43:25 +0200113#define ADDR_REG_OFFSET 5
114#define DATA_REG_OFFSET 6
115
116#define W83627EHF_REG_BANK 0x4E
117#define W83627EHF_REG_CONFIG 0x40
118#define W83627EHF_REG_CHIP_ID 0x49
119#define W83627EHF_REG_MAN_ID 0x4F
120
121static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
122static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
123
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100124/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
125#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
126 (0x554 + (((nr) - 7) * 2)))
127#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
128 (0x555 + (((nr) - 7) * 2)))
129#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
130 (0x550 + (nr) - 7))
131
Jean Delvare08e7e272005-04-25 22:43:25 +0200132#define W83627EHF_REG_TEMP1 0x27
133#define W83627EHF_REG_TEMP1_HYST 0x3a
134#define W83627EHF_REG_TEMP1_OVER 0x39
135static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
136static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
137static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
138static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
139
140/* Fan clock dividers are spread over the following five registers */
141#define W83627EHF_REG_FANDIV1 0x47
142#define W83627EHF_REG_FANDIV2 0x4B
143#define W83627EHF_REG_VBAT 0x5D
144#define W83627EHF_REG_DIODE 0x59
145#define W83627EHF_REG_SMI_OVT 0x4C
146
Jean Delvarea4589db2006-03-23 16:30:29 +0100147#define W83627EHF_REG_ALARM1 0x459
148#define W83627EHF_REG_ALARM2 0x45A
149#define W83627EHF_REG_ALARM3 0x45B
150
Rudolf Marek08c79952006-07-05 18:14:31 +0200151/* SmartFan registers */
152/* DC or PWM output fan configuration */
153static const u8 W83627EHF_REG_PWM_ENABLE[] = {
154 0x04, /* SYS FAN0 output mode and PWM mode */
155 0x04, /* CPU FAN0 output mode and PWM mode */
156 0x12, /* AUX FAN mode */
157 0x62, /* CPU fan1 mode */
158};
159
160static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
161static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
162
163/* FAN Duty Cycle, be used to control */
164static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
165static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
166static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
167
168
169/* Advanced Fan control, some values are common for all fans */
170static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
171static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 };
172
Jean Delvare08e7e272005-04-25 22:43:25 +0200173/*
174 * Conversions
175 */
176
Rudolf Marek08c79952006-07-05 18:14:31 +0200177/* 1 is PWM mode, output in ms */
178static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
179{
180 return mode ? 100 * reg : 400 * reg;
181}
182
183static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
184{
185 return SENSORS_LIMIT((mode ? (msec + 50) / 100 :
186 (msec + 200) / 400), 1, 255);
187}
188
Jean Delvare08e7e272005-04-25 22:43:25 +0200189static inline unsigned int
190fan_from_reg(u8 reg, unsigned int div)
191{
192 if (reg == 0 || reg == 255)
193 return 0;
194 return 1350000U / (reg * div);
195}
196
197static inline unsigned int
198div_from_reg(u8 reg)
199{
200 return 1 << reg;
201}
202
203static inline int
204temp1_from_reg(s8 reg)
205{
206 return reg * 1000;
207}
208
209static inline s8
Rudolf Marek08c79952006-07-05 18:14:31 +0200210temp1_to_reg(int temp, int min, int max)
Jean Delvare08e7e272005-04-25 22:43:25 +0200211{
Rudolf Marek08c79952006-07-05 18:14:31 +0200212 if (temp <= min)
213 return min / 1000;
214 if (temp >= max)
215 return max / 1000;
Jean Delvare08e7e272005-04-25 22:43:25 +0200216 if (temp < 0)
217 return (temp - 500) / 1000;
218 return (temp + 500) / 1000;
219}
220
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100221/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
222
223static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
224
225static inline long in_from_reg(u8 reg, u8 nr)
226{
227 return reg * scale_in[nr];
228}
229
230static inline u8 in_to_reg(u32 val, u8 nr)
231{
232 return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
233}
234
Jean Delvare08e7e272005-04-25 22:43:25 +0200235/*
236 * Data structures and manipulation thereof
237 */
238
239struct w83627ehf_data {
240 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400241 struct class_device *class_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100242 struct mutex lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200243
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100244 struct mutex update_lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200245 char valid; /* !=0 if following fields are valid */
246 unsigned long last_updated; /* In jiffies */
247
248 /* Register values */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100249 u8 in[10]; /* Register value */
250 u8 in_max[10]; /* Register value */
251 u8 in_min[10]; /* Register value */
Jean Delvare08e7e272005-04-25 22:43:25 +0200252 u8 fan[5];
253 u8 fan_min[5];
254 u8 fan_div[5];
255 u8 has_fan; /* some fan inputs can be disabled */
256 s8 temp1;
257 s8 temp1_max;
258 s8 temp1_max_hyst;
259 s16 temp[2];
260 s16 temp_max[2];
261 s16 temp_max_hyst[2];
Jean Delvarea4589db2006-03-23 16:30:29 +0100262 u32 alarms;
Rudolf Marek08c79952006-07-05 18:14:31 +0200263
264 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
265 u8 pwm_enable[4]; /* 1->manual
266 2->thermal cruise (also called SmartFan I) */
267 u8 pwm[4];
268 u8 target_temp[4];
269 u8 tolerance[4];
270
271 u8 fan_min_output[4]; /* minimum fan speed */
272 u8 fan_stop_time[4];
Jean Delvare08e7e272005-04-25 22:43:25 +0200273};
274
275static inline int is_word_sized(u16 reg)
276{
277 return (((reg & 0xff00) == 0x100
278 || (reg & 0xff00) == 0x200)
279 && ((reg & 0x00ff) == 0x50
280 || (reg & 0x00ff) == 0x53
281 || (reg & 0x00ff) == 0x55));
282}
283
284/* We assume that the default bank is 0, thus the following two functions do
285 nothing for registers which live in bank 0. For others, they respectively
286 set the bank register to the correct value (before the register is
287 accessed), and back to 0 (afterwards). */
288static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
289{
290 if (reg & 0xff00) {
291 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
292 outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
293 }
294}
295
296static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
297{
298 if (reg & 0xff00) {
299 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
300 outb_p(0, client->addr + DATA_REG_OFFSET);
301 }
302}
303
304static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
305{
306 struct w83627ehf_data *data = i2c_get_clientdata(client);
307 int res, word_sized = is_word_sized(reg);
308
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100309 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200310
311 w83627ehf_set_bank(client, reg);
312 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
313 res = inb_p(client->addr + DATA_REG_OFFSET);
314 if (word_sized) {
315 outb_p((reg & 0xff) + 1,
316 client->addr + ADDR_REG_OFFSET);
317 res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
318 }
319 w83627ehf_reset_bank(client, reg);
320
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100321 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200322
323 return res;
324}
325
326static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
327{
328 struct w83627ehf_data *data = i2c_get_clientdata(client);
329 int word_sized = is_word_sized(reg);
330
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100331 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200332
333 w83627ehf_set_bank(client, reg);
334 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
335 if (word_sized) {
336 outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
337 outb_p((reg & 0xff) + 1,
338 client->addr + ADDR_REG_OFFSET);
339 }
340 outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
341 w83627ehf_reset_bank(client, reg);
342
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100343 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200344 return 0;
345}
346
347/* This function assumes that the caller holds data->update_lock */
348static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
349{
350 struct w83627ehf_data *data = i2c_get_clientdata(client);
351 u8 reg;
352
353 switch (nr) {
354 case 0:
355 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
356 | ((data->fan_div[0] & 0x03) << 4);
Rudolf Marek14992c72006-10-08 22:02:09 +0200357 /* fan5 input control bit is write only, compute the value */
358 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
Jean Delvare08e7e272005-04-25 22:43:25 +0200359 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
360 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
361 | ((data->fan_div[0] & 0x04) << 3);
362 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
363 break;
364 case 1:
365 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
366 | ((data->fan_div[1] & 0x03) << 6);
Rudolf Marek14992c72006-10-08 22:02:09 +0200367 /* fan5 input control bit is write only, compute the value */
368 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
Jean Delvare08e7e272005-04-25 22:43:25 +0200369 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
370 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
371 | ((data->fan_div[1] & 0x04) << 4);
372 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
373 break;
374 case 2:
375 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
376 | ((data->fan_div[2] & 0x03) << 6);
377 w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
378 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
379 | ((data->fan_div[2] & 0x04) << 5);
380 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
381 break;
382 case 3:
383 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
384 | (data->fan_div[3] & 0x03);
385 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
386 reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
387 | ((data->fan_div[3] & 0x04) << 5);
388 w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
389 break;
390 case 4:
391 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
392 | ((data->fan_div[4] & 0x03) << 3)
393 | ((data->fan_div[4] & 0x04) << 5);
394 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
395 break;
396 }
397}
398
399static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
400{
401 struct i2c_client *client = to_i2c_client(dev);
402 struct w83627ehf_data *data = i2c_get_clientdata(client);
Rudolf Marek08c79952006-07-05 18:14:31 +0200403 int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
Jean Delvare08e7e272005-04-25 22:43:25 +0200404 int i;
405
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100406 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200407
408 if (time_after(jiffies, data->last_updated + HZ)
409 || !data->valid) {
410 /* Fan clock dividers */
411 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
412 data->fan_div[0] = (i >> 4) & 0x03;
413 data->fan_div[1] = (i >> 6) & 0x03;
414 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
415 data->fan_div[2] = (i >> 6) & 0x03;
416 i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
417 data->fan_div[0] |= (i >> 3) & 0x04;
418 data->fan_div[1] |= (i >> 4) & 0x04;
419 data->fan_div[2] |= (i >> 5) & 0x04;
420 if (data->has_fan & ((1 << 3) | (1 << 4))) {
421 i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
422 data->fan_div[3] = i & 0x03;
423 data->fan_div[4] = ((i >> 2) & 0x03)
424 | ((i >> 5) & 0x04);
425 }
426 if (data->has_fan & (1 << 3)) {
427 i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
428 data->fan_div[3] |= (i >> 5) & 0x04;
429 }
430
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100431 /* Measured voltages and limits */
432 for (i = 0; i < 10; i++) {
433 data->in[i] = w83627ehf_read_value(client,
434 W83627EHF_REG_IN(i));
435 data->in_min[i] = w83627ehf_read_value(client,
436 W83627EHF_REG_IN_MIN(i));
437 data->in_max[i] = w83627ehf_read_value(client,
438 W83627EHF_REG_IN_MAX(i));
439 }
440
Jean Delvare08e7e272005-04-25 22:43:25 +0200441 /* Measured fan speeds and limits */
442 for (i = 0; i < 5; i++) {
443 if (!(data->has_fan & (1 << i)))
444 continue;
445
446 data->fan[i] = w83627ehf_read_value(client,
447 W83627EHF_REG_FAN[i]);
448 data->fan_min[i] = w83627ehf_read_value(client,
449 W83627EHF_REG_FAN_MIN[i]);
450
451 /* If we failed to measure the fan speed and clock
452 divider can be increased, let's try that for next
453 time */
454 if (data->fan[i] == 0xff
455 && data->fan_div[i] < 0x07) {
456 dev_dbg(&client->dev, "Increasing fan %d "
457 "clock divider from %u to %u\n",
458 i, div_from_reg(data->fan_div[i]),
459 div_from_reg(data->fan_div[i] + 1));
460 data->fan_div[i]++;
461 w83627ehf_write_fan_div(client, i);
462 /* Preserve min limit if possible */
463 if (data->fan_min[i] >= 2
464 && data->fan_min[i] != 255)
465 w83627ehf_write_value(client,
466 W83627EHF_REG_FAN_MIN[i],
467 (data->fan_min[i] /= 2));
468 }
469 }
470
Rudolf Marek08c79952006-07-05 18:14:31 +0200471 for (i = 0; i < 4; i++) {
472 /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
473 if (i != 1) {
474 pwmcfg = w83627ehf_read_value(client,
475 W83627EHF_REG_PWM_ENABLE[i]);
476 tolerance = w83627ehf_read_value(client,
477 W83627EHF_REG_TOLERANCE[i]);
478 }
479 data->pwm_mode[i] =
480 ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
481 ? 0 : 1;
482 data->pwm_enable[i] =
483 ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
484 & 3) + 1;
485 data->pwm[i] = w83627ehf_read_value(client,
486 W83627EHF_REG_PWM[i]);
487 data->fan_min_output[i] = w83627ehf_read_value(client,
488 W83627EHF_REG_FAN_MIN_OUTPUT[i]);
489 data->fan_stop_time[i] = w83627ehf_read_value(client,
490 W83627EHF_REG_FAN_STOP_TIME[i]);
491 data->target_temp[i] =
492 w83627ehf_read_value(client,
493 W83627EHF_REG_TARGET[i]) &
494 (data->pwm_mode[i] == 1 ? 0x7f : 0xff);
495 data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
496 & 0x0f;
497 }
498
Jean Delvare08e7e272005-04-25 22:43:25 +0200499 /* Measured temperatures and limits */
500 data->temp1 = w83627ehf_read_value(client,
501 W83627EHF_REG_TEMP1);
502 data->temp1_max = w83627ehf_read_value(client,
503 W83627EHF_REG_TEMP1_OVER);
504 data->temp1_max_hyst = w83627ehf_read_value(client,
505 W83627EHF_REG_TEMP1_HYST);
506 for (i = 0; i < 2; i++) {
507 data->temp[i] = w83627ehf_read_value(client,
508 W83627EHF_REG_TEMP[i]);
509 data->temp_max[i] = w83627ehf_read_value(client,
510 W83627EHF_REG_TEMP_OVER[i]);
511 data->temp_max_hyst[i] = w83627ehf_read_value(client,
512 W83627EHF_REG_TEMP_HYST[i]);
513 }
514
Jean Delvarea4589db2006-03-23 16:30:29 +0100515 data->alarms = w83627ehf_read_value(client,
516 W83627EHF_REG_ALARM1) |
517 (w83627ehf_read_value(client,
518 W83627EHF_REG_ALARM2) << 8) |
519 (w83627ehf_read_value(client,
520 W83627EHF_REG_ALARM3) << 16);
521
Jean Delvare08e7e272005-04-25 22:43:25 +0200522 data->last_updated = jiffies;
523 data->valid = 1;
524 }
525
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100526 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200527 return data;
528}
529
530/*
531 * Sysfs callback functions
532 */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100533#define show_in_reg(reg) \
534static ssize_t \
535show_##reg(struct device *dev, struct device_attribute *attr, \
536 char *buf) \
537{ \
538 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
539 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
540 int nr = sensor_attr->index; \
541 return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
542}
543show_in_reg(in)
544show_in_reg(in_min)
545show_in_reg(in_max)
546
547#define store_in_reg(REG, reg) \
548static ssize_t \
549store_in_##reg (struct device *dev, struct device_attribute *attr, \
550 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 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
555 int nr = sensor_attr->index; \
556 u32 val = simple_strtoul(buf, NULL, 10); \
557 \
558 mutex_lock(&data->update_lock); \
559 data->in_##reg[nr] = in_to_reg(val, nr); \
560 w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
561 data->in_##reg[nr]); \
562 mutex_unlock(&data->update_lock); \
563 return count; \
564}
565
566store_in_reg(MIN, min)
567store_in_reg(MAX, max)
568
Jean Delvarea4589db2006-03-23 16:30:29 +0100569static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
570{
571 struct w83627ehf_data *data = w83627ehf_update_device(dev);
572 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
573 int nr = sensor_attr->index;
574 return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01);
575}
576
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100577static struct sensor_device_attribute sda_in_input[] = {
578 SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
579 SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
580 SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
581 SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
582 SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
583 SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
584 SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
585 SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
586 SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
587 SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
588};
589
Jean Delvarea4589db2006-03-23 16:30:29 +0100590static struct sensor_device_attribute sda_in_alarm[] = {
591 SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
592 SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
593 SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
594 SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
595 SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
596 SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21),
597 SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20),
598 SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16),
599 SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17),
600 SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),
601};
602
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100603static struct sensor_device_attribute sda_in_min[] = {
604 SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
605 SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
606 SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
607 SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
608 SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
609 SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
610 SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
611 SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
612 SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
613 SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
614};
615
616static struct sensor_device_attribute sda_in_max[] = {
617 SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
618 SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
619 SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
620 SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
621 SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
622 SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
623 SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
624 SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
625 SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
626 SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
627};
628
Jean Delvare08e7e272005-04-25 22:43:25 +0200629#define show_fan_reg(reg) \
630static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100631show_##reg(struct device *dev, struct device_attribute *attr, \
632 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200633{ \
634 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100635 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
636 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200637 return sprintf(buf, "%d\n", \
638 fan_from_reg(data->reg[nr], \
639 div_from_reg(data->fan_div[nr]))); \
640}
641show_fan_reg(fan);
642show_fan_reg(fan_min);
643
644static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100645show_fan_div(struct device *dev, struct device_attribute *attr,
646 char *buf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200647{
648 struct w83627ehf_data *data = w83627ehf_update_device(dev);
Yuan Mu412fec82006-02-05 23:24:16 +0100649 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
650 int nr = sensor_attr->index;
651 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
Jean Delvare08e7e272005-04-25 22:43:25 +0200652}
653
654static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100655store_fan_min(struct device *dev, struct device_attribute *attr,
656 const char *buf, size_t count)
Jean Delvare08e7e272005-04-25 22:43:25 +0200657{
658 struct i2c_client *client = to_i2c_client(dev);
659 struct w83627ehf_data *data = i2c_get_clientdata(client);
Yuan Mu412fec82006-02-05 23:24:16 +0100660 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
661 int nr = sensor_attr->index;
Jean Delvare08e7e272005-04-25 22:43:25 +0200662 unsigned int val = simple_strtoul(buf, NULL, 10);
663 unsigned int reg;
664 u8 new_div;
665
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100666 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200667 if (!val) {
668 /* No min limit, alarm disabled */
669 data->fan_min[nr] = 255;
670 new_div = data->fan_div[nr]; /* No change */
671 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
672 } else if ((reg = 1350000U / val) >= 128 * 255) {
673 /* Speed below this value cannot possibly be represented,
674 even with the highest divider (128) */
675 data->fan_min[nr] = 254;
676 new_div = 7; /* 128 == (1 << 7) */
677 dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
678 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
679 } else if (!reg) {
680 /* Speed above this value cannot possibly be represented,
681 even with the lowest divider (1) */
682 data->fan_min[nr] = 1;
683 new_div = 0; /* 1 == (1 << 0) */
684 dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
Jean Delvareb9110b12005-05-02 23:08:22 +0200685 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
Jean Delvare08e7e272005-04-25 22:43:25 +0200686 } else {
687 /* Automatically pick the best divider, i.e. the one such
688 that the min limit will correspond to a register value
689 in the 96..192 range */
690 new_div = 0;
691 while (reg > 192 && new_div < 7) {
692 reg >>= 1;
693 new_div++;
694 }
695 data->fan_min[nr] = reg;
696 }
697
698 /* Write both the fan clock divider (if it changed) and the new
699 fan min (unconditionally) */
700 if (new_div != data->fan_div[nr]) {
701 if (new_div > data->fan_div[nr])
702 data->fan[nr] >>= (data->fan_div[nr] - new_div);
703 else
704 data->fan[nr] <<= (new_div - data->fan_div[nr]);
705
706 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
707 nr + 1, div_from_reg(data->fan_div[nr]),
708 div_from_reg(new_div));
709 data->fan_div[nr] = new_div;
710 w83627ehf_write_fan_div(client, nr);
711 }
712 w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
713 data->fan_min[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100714 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200715
716 return count;
717}
718
Yuan Mu412fec82006-02-05 23:24:16 +0100719static struct sensor_device_attribute sda_fan_input[] = {
720 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
721 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
722 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
723 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
724 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
725};
Jean Delvare08e7e272005-04-25 22:43:25 +0200726
Jean Delvarea4589db2006-03-23 16:30:29 +0100727static struct sensor_device_attribute sda_fan_alarm[] = {
728 SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
729 SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
730 SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
731 SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10),
732 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),
733};
734
Yuan Mu412fec82006-02-05 23:24:16 +0100735static struct sensor_device_attribute sda_fan_min[] = {
736 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
737 store_fan_min, 0),
738 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
739 store_fan_min, 1),
740 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
741 store_fan_min, 2),
742 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
743 store_fan_min, 3),
744 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
745 store_fan_min, 4),
746};
Jean Delvare08e7e272005-04-25 22:43:25 +0200747
Yuan Mu412fec82006-02-05 23:24:16 +0100748static struct sensor_device_attribute sda_fan_div[] = {
749 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
750 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
751 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
752 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
753 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
754};
Jean Delvare08e7e272005-04-25 22:43:25 +0200755
Jean Delvare08e7e272005-04-25 22:43:25 +0200756#define show_temp1_reg(reg) \
757static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700758show_##reg(struct device *dev, struct device_attribute *attr, \
759 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200760{ \
761 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
762 return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
763}
764show_temp1_reg(temp1);
765show_temp1_reg(temp1_max);
766show_temp1_reg(temp1_max_hyst);
767
768#define store_temp1_reg(REG, reg) \
769static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700770store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
771 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200772{ \
773 struct i2c_client *client = to_i2c_client(dev); \
774 struct w83627ehf_data *data = i2c_get_clientdata(client); \
775 u32 val = simple_strtoul(buf, NULL, 10); \
776 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100777 mutex_lock(&data->update_lock); \
Rudolf Marek08c79952006-07-05 18:14:31 +0200778 data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200779 w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
780 data->temp1_##reg); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100781 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200782 return count; \
783}
784store_temp1_reg(OVER, max);
785store_temp1_reg(HYST, max_hyst);
786
Jean Delvare08e7e272005-04-25 22:43:25 +0200787#define show_temp_reg(reg) \
788static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100789show_##reg(struct device *dev, struct device_attribute *attr, \
790 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200791{ \
792 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100793 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
794 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200795 return sprintf(buf, "%d\n", \
796 LM75_TEMP_FROM_REG(data->reg[nr])); \
797}
798show_temp_reg(temp);
799show_temp_reg(temp_max);
800show_temp_reg(temp_max_hyst);
801
802#define store_temp_reg(REG, reg) \
803static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100804store_##reg(struct device *dev, struct device_attribute *attr, \
805 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200806{ \
807 struct i2c_client *client = to_i2c_client(dev); \
808 struct w83627ehf_data *data = i2c_get_clientdata(client); \
Yuan Mu412fec82006-02-05 23:24:16 +0100809 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
810 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200811 u32 val = simple_strtoul(buf, NULL, 10); \
812 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100813 mutex_lock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200814 data->reg[nr] = LM75_TEMP_TO_REG(val); \
815 w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
816 data->reg[nr]); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100817 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200818 return count; \
819}
820store_temp_reg(OVER, temp_max);
821store_temp_reg(HYST, temp_max_hyst);
822
Yuan Mu412fec82006-02-05 23:24:16 +0100823static struct sensor_device_attribute sda_temp[] = {
824 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
825 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
826 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
827 SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
828 store_temp1_max, 0),
829 SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
830 store_temp_max, 0),
831 SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
832 store_temp_max, 1),
833 SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
834 store_temp1_max_hyst, 0),
835 SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
836 store_temp_max_hyst, 0),
837 SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
838 store_temp_max_hyst, 1),
Jean Delvarea4589db2006-03-23 16:30:29 +0100839 SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
840 SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
841 SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
Yuan Mu412fec82006-02-05 23:24:16 +0100842};
Jean Delvare08e7e272005-04-25 22:43:25 +0200843
Rudolf Marek08c79952006-07-05 18:14:31 +0200844#define show_pwm_reg(reg) \
845static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
846 char *buf) \
847{ \
848 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
849 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
850 int nr = sensor_attr->index; \
851 return sprintf(buf, "%d\n", data->reg[nr]); \
852}
853
854show_pwm_reg(pwm_mode)
855show_pwm_reg(pwm_enable)
856show_pwm_reg(pwm)
857
858static ssize_t
859store_pwm_mode(struct device *dev, struct device_attribute *attr,
860 const char *buf, size_t count)
861{
862 struct i2c_client *client = to_i2c_client(dev);
863 struct w83627ehf_data *data = i2c_get_clientdata(client);
864 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
865 int nr = sensor_attr->index;
866 u32 val = simple_strtoul(buf, NULL, 10);
867 u16 reg;
868
869 if (val > 1)
870 return -EINVAL;
871 mutex_lock(&data->update_lock);
872 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
873 data->pwm_mode[nr] = val;
874 reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
875 if (!val)
876 reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
877 w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
878 mutex_unlock(&data->update_lock);
879 return count;
880}
881
882static ssize_t
883store_pwm(struct device *dev, struct device_attribute *attr,
884 const char *buf, size_t count)
885{
886 struct i2c_client *client = to_i2c_client(dev);
887 struct w83627ehf_data *data = i2c_get_clientdata(client);
888 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
889 int nr = sensor_attr->index;
890 u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
891
892 mutex_lock(&data->update_lock);
893 data->pwm[nr] = val;
894 w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val);
895 mutex_unlock(&data->update_lock);
896 return count;
897}
898
899static ssize_t
900store_pwm_enable(struct device *dev, struct device_attribute *attr,
901 const char *buf, size_t count)
902{
903 struct i2c_client *client = to_i2c_client(dev);
904 struct w83627ehf_data *data = i2c_get_clientdata(client);
905 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
906 int nr = sensor_attr->index;
907 u32 val = simple_strtoul(buf, NULL, 10);
908 u16 reg;
909
910 if (!val || (val > 2)) /* only modes 1 and 2 are supported */
911 return -EINVAL;
912 mutex_lock(&data->update_lock);
913 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
914 data->pwm_enable[nr] = val;
915 reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
916 reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
917 w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
918 mutex_unlock(&data->update_lock);
919 return count;
920}
921
922
923#define show_tol_temp(reg) \
924static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
925 char *buf) \
926{ \
927 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
928 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
929 int nr = sensor_attr->index; \
930 return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
931}
932
933show_tol_temp(tolerance)
934show_tol_temp(target_temp)
935
936static ssize_t
937store_target_temp(struct device *dev, struct device_attribute *attr,
938 const char *buf, size_t count)
939{
940 struct i2c_client *client = to_i2c_client(dev);
941 struct w83627ehf_data *data = i2c_get_clientdata(client);
942 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
943 int nr = sensor_attr->index;
944 u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
945
946 mutex_lock(&data->update_lock);
947 data->target_temp[nr] = val;
948 w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val);
949 mutex_unlock(&data->update_lock);
950 return count;
951}
952
953static ssize_t
954store_tolerance(struct device *dev, struct device_attribute *attr,
955 const char *buf, size_t count)
956{
957 struct i2c_client *client = to_i2c_client(dev);
958 struct w83627ehf_data *data = i2c_get_clientdata(client);
959 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
960 int nr = sensor_attr->index;
961 u16 reg;
962 /* Limit the temp to 0C - 15C */
963 u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
964
965 mutex_lock(&data->update_lock);
966 reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]);
967 data->tolerance[nr] = val;
968 if (nr == 1)
969 reg = (reg & 0x0f) | (val << 4);
970 else
971 reg = (reg & 0xf0) | val;
972 w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg);
973 mutex_unlock(&data->update_lock);
974 return count;
975}
976
977static struct sensor_device_attribute sda_pwm[] = {
978 SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
979 SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
980 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
981 SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
982};
983
984static struct sensor_device_attribute sda_pwm_mode[] = {
985 SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
986 store_pwm_mode, 0),
987 SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
988 store_pwm_mode, 1),
989 SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
990 store_pwm_mode, 2),
991 SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
992 store_pwm_mode, 3),
993};
994
995static struct sensor_device_attribute sda_pwm_enable[] = {
996 SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
997 store_pwm_enable, 0),
998 SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
999 store_pwm_enable, 1),
1000 SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1001 store_pwm_enable, 2),
1002 SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1003 store_pwm_enable, 3),
1004};
1005
1006static struct sensor_device_attribute sda_target_temp[] = {
1007 SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
1008 store_target_temp, 0),
1009 SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
1010 store_target_temp, 1),
1011 SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
1012 store_target_temp, 2),
1013 SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
1014 store_target_temp, 3),
1015};
1016
1017static struct sensor_device_attribute sda_tolerance[] = {
1018 SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1019 store_tolerance, 0),
1020 SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1021 store_tolerance, 1),
1022 SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1023 store_tolerance, 2),
1024 SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1025 store_tolerance, 3),
1026};
1027
Rudolf Marek08c79952006-07-05 18:14:31 +02001028/* Smart Fan registers */
1029
1030#define fan_functions(reg, REG) \
1031static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1032 char *buf) \
1033{ \
1034 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
1035 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1036 int nr = sensor_attr->index; \
1037 return sprintf(buf, "%d\n", data->reg[nr]); \
1038}\
1039static ssize_t \
1040store_##reg(struct device *dev, struct device_attribute *attr, \
1041 const char *buf, size_t count) \
1042{\
1043 struct i2c_client *client = to_i2c_client(dev); \
1044 struct w83627ehf_data *data = i2c_get_clientdata(client); \
1045 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1046 int nr = sensor_attr->index; \
1047 u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
1048 mutex_lock(&data->update_lock); \
1049 data->reg[nr] = val; \
1050 w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
1051 mutex_unlock(&data->update_lock); \
1052 return count; \
1053}
1054
1055fan_functions(fan_min_output, FAN_MIN_OUTPUT)
1056
1057#define fan_time_functions(reg, REG) \
1058static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1059 char *buf) \
1060{ \
1061 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
1062 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1063 int nr = sensor_attr->index; \
1064 return sprintf(buf, "%d\n", \
1065 step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
1066} \
1067\
1068static ssize_t \
1069store_##reg(struct device *dev, struct device_attribute *attr, \
1070 const char *buf, size_t count) \
1071{ \
1072 struct i2c_client *client = to_i2c_client(dev); \
1073 struct w83627ehf_data *data = i2c_get_clientdata(client); \
1074 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1075 int nr = sensor_attr->index; \
1076 u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
1077 data->pwm_mode[nr]); \
1078 mutex_lock(&data->update_lock); \
1079 data->reg[nr] = val; \
1080 w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
1081 mutex_unlock(&data->update_lock); \
1082 return count; \
1083} \
1084
1085fan_time_functions(fan_stop_time, FAN_STOP_TIME)
1086
1087
1088static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
1089 SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1090 store_fan_stop_time, 3),
1091 SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1092 store_fan_min_output, 3),
1093};
1094
1095static struct sensor_device_attribute sda_sf3_arrays[] = {
1096 SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1097 store_fan_stop_time, 0),
1098 SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1099 store_fan_stop_time, 1),
1100 SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1101 store_fan_stop_time, 2),
1102 SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1103 store_fan_min_output, 0),
1104 SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1105 store_fan_min_output, 1),
1106 SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1107 store_fan_min_output, 2),
1108};
1109
Jean Delvare08e7e272005-04-25 22:43:25 +02001110/*
1111 * Driver and client management
1112 */
1113
David Hubbardc18beb52006-09-24 21:04:38 +02001114static void w83627ehf_device_remove_files(struct device *dev)
1115{
1116 /* some entries in the following arrays may not have been used in
1117 * device_create_file(), but device_remove_file() will ignore them */
1118 int i;
1119
1120 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
1121 device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
1122 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
1123 device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
1124 for (i = 0; i < 10; i++) {
1125 device_remove_file(dev, &sda_in_input[i].dev_attr);
1126 device_remove_file(dev, &sda_in_alarm[i].dev_attr);
1127 device_remove_file(dev, &sda_in_min[i].dev_attr);
1128 device_remove_file(dev, &sda_in_max[i].dev_attr);
1129 }
1130 for (i = 0; i < 5; i++) {
1131 device_remove_file(dev, &sda_fan_input[i].dev_attr);
1132 device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
1133 device_remove_file(dev, &sda_fan_div[i].dev_attr);
1134 device_remove_file(dev, &sda_fan_min[i].dev_attr);
1135 }
1136 for (i = 0; i < 4; i++) {
1137 device_remove_file(dev, &sda_pwm[i].dev_attr);
1138 device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
1139 device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
1140 device_remove_file(dev, &sda_target_temp[i].dev_attr);
1141 device_remove_file(dev, &sda_tolerance[i].dev_attr);
1142 }
1143 for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
1144 device_remove_file(dev, &sda_temp[i].dev_attr);
1145}
1146
Jean Delvare08e7e272005-04-25 22:43:25 +02001147static struct i2c_driver w83627ehf_driver;
1148
1149static void w83627ehf_init_client(struct i2c_client *client)
1150{
1151 int i;
1152 u8 tmp;
1153
1154 /* Start monitoring is needed */
1155 tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
1156 if (!(tmp & 0x01))
1157 w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
1158 tmp | 0x01);
1159
1160 /* Enable temp2 and temp3 if needed */
1161 for (i = 0; i < 2; i++) {
1162 tmp = w83627ehf_read_value(client,
1163 W83627EHF_REG_TEMP_CONFIG[i]);
1164 if (tmp & 0x01)
1165 w83627ehf_write_value(client,
1166 W83627EHF_REG_TEMP_CONFIG[i],
1167 tmp & 0xfe);
1168 }
1169}
1170
Jean Delvare2d8672c2005-07-19 23:56:35 +02001171static int w83627ehf_detect(struct i2c_adapter *adapter)
Jean Delvare08e7e272005-04-25 22:43:25 +02001172{
1173 struct i2c_client *client;
1174 struct w83627ehf_data *data;
Yuan Mu412fec82006-02-05 23:24:16 +01001175 struct device *dev;
Rudolf Marek08c79952006-07-05 18:14:31 +02001176 u8 fan4pin, fan5pin;
Jean Delvare08e7e272005-04-25 22:43:25 +02001177 int i, err = 0;
1178
Petr Vandrovecada0c2f2005-10-07 23:11:03 +02001179 if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001180 w83627ehf_driver.driver.name)) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001181 err = -EBUSY;
1182 goto exit;
1183 }
1184
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001185 if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001186 err = -ENOMEM;
1187 goto exit_release;
1188 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001189
1190 client = &data->client;
1191 i2c_set_clientdata(client, data);
1192 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001193 mutex_init(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +02001194 client->adapter = adapter;
1195 client->driver = &w83627ehf_driver;
1196 client->flags = 0;
Yuan Mu412fec82006-02-05 23:24:16 +01001197 dev = &client->dev;
Jean Delvare08e7e272005-04-25 22:43:25 +02001198
1199 strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
1200 data->valid = 0;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001201 mutex_init(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +02001202
1203 /* Tell the i2c layer a new client has arrived */
1204 if ((err = i2c_attach_client(client)))
1205 goto exit_free;
1206
1207 /* Initialize the chip */
1208 w83627ehf_init_client(client);
1209
1210 /* A few vars need to be filled upon startup */
1211 for (i = 0; i < 5; i++)
1212 data->fan_min[i] = w83627ehf_read_value(client,
1213 W83627EHF_REG_FAN_MIN[i]);
1214
Rudolf Marek08c79952006-07-05 18:14:31 +02001215 /* fan4 and fan5 share some pins with the GPIO and serial flash */
1216
1217 superio_enter();
1218 fan5pin = superio_inb(0x24) & 0x2;
1219 fan4pin = superio_inb(0x29) & 0x6;
1220 superio_exit();
1221
Jean Delvare08e7e272005-04-25 22:43:25 +02001222 /* It looks like fan4 and fan5 pins can be alternatively used
Rudolf Marek14992c72006-10-08 22:02:09 +02001223 as fan on/off switches, but fan5 control is write only :/
1224 We assume that if the serial interface is disabled, designers
1225 connected fan5 as input unless they are emitting log 1, which
1226 is not the default. */
Rudolf Marek08c79952006-07-05 18:14:31 +02001227
Jean Delvare08e7e272005-04-25 22:43:25 +02001228 data->has_fan = 0x07; /* fan1, fan2 and fan3 */
1229 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
Rudolf Marek08c79952006-07-05 18:14:31 +02001230 if ((i & (1 << 2)) && (!fan4pin))
Jean Delvare08e7e272005-04-25 22:43:25 +02001231 data->has_fan |= (1 << 3);
Rudolf Marek14992c72006-10-08 22:02:09 +02001232 if (!(i & (1 << 1)) && (!fan5pin))
Jean Delvare08e7e272005-04-25 22:43:25 +02001233 data->has_fan |= (1 << 4);
1234
1235 /* Register sysfs hooks */
Rudolf Marek08c79952006-07-05 18:14:31 +02001236 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001237 if ((err = device_create_file(dev,
1238 &sda_sf3_arrays[i].dev_attr)))
1239 goto exit_remove;
Rudolf Marek08c79952006-07-05 18:14:31 +02001240
1241 /* if fan4 is enabled create the sf3 files for it */
1242 if (data->has_fan & (1 << 3))
David Hubbardc18beb52006-09-24 21:04:38 +02001243 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
1244 if ((err = device_create_file(dev,
1245 &sda_sf3_arrays_fan4[i].dev_attr)))
1246 goto exit_remove;
1247 }
Rudolf Marek08c79952006-07-05 18:14:31 +02001248
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001249 for (i = 0; i < 10; i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001250 if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
1251 || (err = device_create_file(dev,
1252 &sda_in_alarm[i].dev_attr))
1253 || (err = device_create_file(dev,
1254 &sda_in_min[i].dev_attr))
1255 || (err = device_create_file(dev,
1256 &sda_in_max[i].dev_attr)))
1257 goto exit_remove;
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001258
Yuan Mu412fec82006-02-05 23:24:16 +01001259 for (i = 0; i < 5; i++) {
Rudolf Marek08c79952006-07-05 18:14:31 +02001260 if (data->has_fan & (1 << i)) {
David Hubbardc18beb52006-09-24 21:04:38 +02001261 if ((err = device_create_file(dev,
1262 &sda_fan_input[i].dev_attr))
1263 || (err = device_create_file(dev,
1264 &sda_fan_alarm[i].dev_attr))
1265 || (err = device_create_file(dev,
1266 &sda_fan_div[i].dev_attr))
1267 || (err = device_create_file(dev,
1268 &sda_fan_min[i].dev_attr)))
1269 goto exit_remove;
1270 if (i < 4 && /* w83627ehf only has 4 pwm */
1271 ((err = device_create_file(dev,
1272 &sda_pwm[i].dev_attr))
1273 || (err = device_create_file(dev,
1274 &sda_pwm_mode[i].dev_attr))
1275 || (err = device_create_file(dev,
1276 &sda_pwm_enable[i].dev_attr))
1277 || (err = device_create_file(dev,
1278 &sda_target_temp[i].dev_attr))
1279 || (err = device_create_file(dev,
1280 &sda_tolerance[i].dev_attr))))
1281 goto exit_remove;
Rudolf Marek08c79952006-07-05 18:14:31 +02001282 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001283 }
Rudolf Marek08c79952006-07-05 18:14:31 +02001284
Yuan Mu412fec82006-02-05 23:24:16 +01001285 for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001286 if ((err = device_create_file(dev, &sda_temp[i].dev_attr)))
1287 goto exit_remove;
1288
1289 data->class_dev = hwmon_device_register(dev);
1290 if (IS_ERR(data->class_dev)) {
1291 err = PTR_ERR(data->class_dev);
1292 goto exit_remove;
1293 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001294
1295 return 0;
1296
David Hubbardc18beb52006-09-24 21:04:38 +02001297exit_remove:
1298 w83627ehf_device_remove_files(dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001299 i2c_detach_client(client);
Jean Delvare08e7e272005-04-25 22:43:25 +02001300exit_free:
1301 kfree(data);
1302exit_release:
Petr Vandrovecada0c2f2005-10-07 23:11:03 +02001303 release_region(address + REGION_OFFSET, REGION_LENGTH);
Jean Delvare08e7e272005-04-25 22:43:25 +02001304exit:
1305 return err;
1306}
1307
Jean Delvare08e7e272005-04-25 22:43:25 +02001308static int w83627ehf_detach_client(struct i2c_client *client)
1309{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001310 struct w83627ehf_data *data = i2c_get_clientdata(client);
Jean Delvare08e7e272005-04-25 22:43:25 +02001311 int err;
1312
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001313 hwmon_device_unregister(data->class_dev);
David Hubbardc18beb52006-09-24 21:04:38 +02001314 w83627ehf_device_remove_files(&client->dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001315
Jean Delvare7bef5592005-07-27 22:14:49 +02001316 if ((err = i2c_detach_client(client)))
Jean Delvare08e7e272005-04-25 22:43:25 +02001317 return err;
Petr Vandrovecada0c2f2005-10-07 23:11:03 +02001318 release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001319 kfree(data);
Jean Delvare08e7e272005-04-25 22:43:25 +02001320
1321 return 0;
1322}
1323
1324static struct i2c_driver w83627ehf_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001325 .driver = {
Jean Delvare87218842006-09-03 22:36:14 +02001326 .owner = THIS_MODULE,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001327 .name = "w83627ehf",
1328 },
Jean Delvare2d8672c2005-07-19 23:56:35 +02001329 .attach_adapter = w83627ehf_detect,
Jean Delvare08e7e272005-04-25 22:43:25 +02001330 .detach_client = w83627ehf_detach_client,
1331};
1332
Jean Delvare2d8672c2005-07-19 23:56:35 +02001333static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
Jean Delvare08e7e272005-04-25 22:43:25 +02001334{
1335 u16 val;
1336
1337 REG = sioaddr;
1338 VAL = sioaddr + 1;
1339 superio_enter();
1340
1341 val = (superio_inb(SIO_REG_DEVID) << 8)
1342 | superio_inb(SIO_REG_DEVID + 1);
1343 if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
1344 superio_exit();
1345 return -ENODEV;
1346 }
1347
1348 superio_select(W83627EHF_LD_HWM);
1349 val = (superio_inb(SIO_REG_ADDR) << 8)
1350 | superio_inb(SIO_REG_ADDR + 1);
Petr Vandrovecada0c2f2005-10-07 23:11:03 +02001351 *addr = val & REGION_ALIGNMENT;
Jean Delvare2d8672c2005-07-19 23:56:35 +02001352 if (*addr == 0) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001353 superio_exit();
1354 return -ENODEV;
1355 }
1356
1357 /* Activate logical device if needed */
1358 val = superio_inb(SIO_REG_ENABLE);
1359 if (!(val & 0x01))
1360 superio_outb(SIO_REG_ENABLE, val | 0x01);
1361
1362 superio_exit();
1363 return 0;
1364}
1365
1366static int __init sensors_w83627ehf_init(void)
1367{
Jean Delvare2d8672c2005-07-19 23:56:35 +02001368 if (w83627ehf_find(0x2e, &address)
1369 && w83627ehf_find(0x4e, &address))
Jean Delvare08e7e272005-04-25 22:43:25 +02001370 return -ENODEV;
1371
Jean Delvarefde09502005-07-19 23:51:07 +02001372 return i2c_isa_add_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +02001373}
1374
1375static void __exit sensors_w83627ehf_exit(void)
1376{
Jean Delvarefde09502005-07-19 23:51:07 +02001377 i2c_isa_del_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +02001378}
1379
1380MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
1381MODULE_DESCRIPTION("W83627EHF driver");
1382MODULE_LICENSE("GPL");
1383
1384module_init(sensors_w83627ehf_init);
1385module_exit(sensors_w83627ehf_exit);