blob: f4d850c71585624043891084a89d80617c6e5479 [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
David Hubbard657c93b2007-02-14 21:15:04 +010035 Chip #vin #fan #pwm #temp chip IDs man ID
36 w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3
37 0x8860 0xa1
38 w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3
Jean Delvare08e7e272005-04-25 22:43:25 +020039*/
40
41#include <linux/module.h>
42#include <linux/init.h>
43#include <linux/slab.h>
44#include <linux/i2c.h>
Jean Delvarefde09502005-07-19 23:51:07 +020045#include <linux/i2c-isa.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040046#include <linux/hwmon.h>
Yuan Mu412fec82006-02-05 23:24:16 +010047#include <linux/hwmon-sysfs.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040048#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010049#include <linux/mutex.h>
Jean Delvare08e7e272005-04-25 22:43:25 +020050#include <asm/io.h>
51#include "lm75.h"
52
Jean Delvare2d8672c2005-07-19 23:56:35 +020053/* The actual ISA address is read from Super-I/O configuration space */
54static unsigned short address;
Jean Delvare08e7e272005-04-25 22:43:25 +020055
56/*
57 * Super-I/O constants and functions
58 */
59
David Hubbard657c93b2007-02-14 21:15:04 +010060/*
61 * The three following globals are initialized in w83627ehf_find(), before
62 * the i2c-isa device is created. Otherwise, they could be stored in
63 * w83627ehf_data. This is ugly, but necessary, and when the driver is next
64 * updated to become a platform driver, the globals will disappear.
65 */
Jean Delvare08e7e272005-04-25 22:43:25 +020066static int REG; /* The register to read/write */
67static int VAL; /* The value to read/write */
David Hubbard657c93b2007-02-14 21:15:04 +010068/* The w83627ehf/ehg have 10 voltage inputs, but the w83627dhg has 9. This
69 * value is also used in w83627ehf_detect() to export a device name in sysfs
70 * (e.g. w83627ehf or w83627dhg) */
71static int w83627ehf_num_in;
Jean Delvare08e7e272005-04-25 22:43:25 +020072
73#define W83627EHF_LD_HWM 0x0b
74
75#define SIO_REG_LDSEL 0x07 /* Logical device select */
76#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
77#define SIO_REG_ENABLE 0x30 /* Logical device enable */
78#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
79
David Hubbard657c93b2007-02-14 21:15:04 +010080#define SIO_W83627EHF_ID 0x8850
81#define SIO_W83627EHG_ID 0x8860
82#define SIO_W83627DHG_ID 0xa020
83#define SIO_ID_MASK 0xFFF0
Jean Delvare08e7e272005-04-25 22:43:25 +020084
85static inline void
86superio_outb(int reg, int val)
87{
88 outb(reg, REG);
89 outb(val, VAL);
90}
91
92static inline int
93superio_inb(int reg)
94{
95 outb(reg, REG);
96 return inb(VAL);
97}
98
99static inline void
100superio_select(int ld)
101{
102 outb(SIO_REG_LDSEL, REG);
103 outb(ld, VAL);
104}
105
106static inline void
107superio_enter(void)
108{
109 outb(0x87, REG);
110 outb(0x87, REG);
111}
112
113static inline void
114superio_exit(void)
115{
116 outb(0x02, REG);
117 outb(0x02, VAL);
118}
119
120/*
121 * ISA constants
122 */
123
Jean Delvare1a641fc2007-04-23 14:41:16 -0700124#define IOREGION_ALIGNMENT ~7
125#define IOREGION_OFFSET 5
126#define IOREGION_LENGTH 2
Jean Delvare08e7e272005-04-25 22:43:25 +0200127#define ADDR_REG_OFFSET 5
128#define DATA_REG_OFFSET 6
129
130#define W83627EHF_REG_BANK 0x4E
131#define W83627EHF_REG_CONFIG 0x40
David Hubbard657c93b2007-02-14 21:15:04 +0100132
133/* Not currently used:
134 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
135 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
136 * REG_MAN_ID is at port 0x4f
137 * REG_CHIP_ID is at port 0x58 */
Jean Delvare08e7e272005-04-25 22:43:25 +0200138
139static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
140static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
141
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100142/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
143#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
144 (0x554 + (((nr) - 7) * 2)))
145#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
146 (0x555 + (((nr) - 7) * 2)))
147#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
148 (0x550 + (nr) - 7))
149
Jean Delvare08e7e272005-04-25 22:43:25 +0200150#define W83627EHF_REG_TEMP1 0x27
151#define W83627EHF_REG_TEMP1_HYST 0x3a
152#define W83627EHF_REG_TEMP1_OVER 0x39
153static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
154static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
155static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
156static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
157
158/* Fan clock dividers are spread over the following five registers */
159#define W83627EHF_REG_FANDIV1 0x47
160#define W83627EHF_REG_FANDIV2 0x4B
161#define W83627EHF_REG_VBAT 0x5D
162#define W83627EHF_REG_DIODE 0x59
163#define W83627EHF_REG_SMI_OVT 0x4C
164
Jean Delvarea4589db2006-03-23 16:30:29 +0100165#define W83627EHF_REG_ALARM1 0x459
166#define W83627EHF_REG_ALARM2 0x45A
167#define W83627EHF_REG_ALARM3 0x45B
168
Rudolf Marek08c79952006-07-05 18:14:31 +0200169/* SmartFan registers */
170/* DC or PWM output fan configuration */
171static const u8 W83627EHF_REG_PWM_ENABLE[] = {
172 0x04, /* SYS FAN0 output mode and PWM mode */
173 0x04, /* CPU FAN0 output mode and PWM mode */
174 0x12, /* AUX FAN mode */
175 0x62, /* CPU fan1 mode */
176};
177
178static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
179static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
180
181/* FAN Duty Cycle, be used to control */
182static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
183static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
184static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
185
186
187/* Advanced Fan control, some values are common for all fans */
188static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
189static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 };
190
Jean Delvare08e7e272005-04-25 22:43:25 +0200191/*
192 * Conversions
193 */
194
Rudolf Marek08c79952006-07-05 18:14:31 +0200195/* 1 is PWM mode, output in ms */
196static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
197{
198 return mode ? 100 * reg : 400 * reg;
199}
200
201static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
202{
203 return SENSORS_LIMIT((mode ? (msec + 50) / 100 :
204 (msec + 200) / 400), 1, 255);
205}
206
Jean Delvare08e7e272005-04-25 22:43:25 +0200207static inline unsigned int
208fan_from_reg(u8 reg, unsigned int div)
209{
210 if (reg == 0 || reg == 255)
211 return 0;
212 return 1350000U / (reg * div);
213}
214
215static inline unsigned int
216div_from_reg(u8 reg)
217{
218 return 1 << reg;
219}
220
221static inline int
222temp1_from_reg(s8 reg)
223{
224 return reg * 1000;
225}
226
227static inline s8
Rudolf Marek08c79952006-07-05 18:14:31 +0200228temp1_to_reg(int temp, int min, int max)
Jean Delvare08e7e272005-04-25 22:43:25 +0200229{
Rudolf Marek08c79952006-07-05 18:14:31 +0200230 if (temp <= min)
231 return min / 1000;
232 if (temp >= max)
233 return max / 1000;
Jean Delvare08e7e272005-04-25 22:43:25 +0200234 if (temp < 0)
235 return (temp - 500) / 1000;
236 return (temp + 500) / 1000;
237}
238
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100239/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
240
241static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
242
243static inline long in_from_reg(u8 reg, u8 nr)
244{
245 return reg * scale_in[nr];
246}
247
248static inline u8 in_to_reg(u32 val, u8 nr)
249{
250 return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
251}
252
Jean Delvare08e7e272005-04-25 22:43:25 +0200253/*
254 * Data structures and manipulation thereof
255 */
256
257struct w83627ehf_data {
258 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400259 struct class_device *class_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100260 struct mutex lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200261
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100262 struct mutex update_lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200263 char valid; /* !=0 if following fields are valid */
264 unsigned long last_updated; /* In jiffies */
265
266 /* Register values */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100267 u8 in[10]; /* Register value */
268 u8 in_max[10]; /* Register value */
269 u8 in_min[10]; /* Register value */
Jean Delvare08e7e272005-04-25 22:43:25 +0200270 u8 fan[5];
271 u8 fan_min[5];
272 u8 fan_div[5];
273 u8 has_fan; /* some fan inputs can be disabled */
274 s8 temp1;
275 s8 temp1_max;
276 s8 temp1_max_hyst;
277 s16 temp[2];
278 s16 temp_max[2];
279 s16 temp_max_hyst[2];
Jean Delvarea4589db2006-03-23 16:30:29 +0100280 u32 alarms;
Rudolf Marek08c79952006-07-05 18:14:31 +0200281
282 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
283 u8 pwm_enable[4]; /* 1->manual
284 2->thermal cruise (also called SmartFan I) */
285 u8 pwm[4];
286 u8 target_temp[4];
287 u8 tolerance[4];
288
289 u8 fan_min_output[4]; /* minimum fan speed */
290 u8 fan_stop_time[4];
Jean Delvare08e7e272005-04-25 22:43:25 +0200291};
292
293static inline int is_word_sized(u16 reg)
294{
295 return (((reg & 0xff00) == 0x100
296 || (reg & 0xff00) == 0x200)
297 && ((reg & 0x00ff) == 0x50
298 || (reg & 0x00ff) == 0x53
299 || (reg & 0x00ff) == 0x55));
300}
301
302/* We assume that the default bank is 0, thus the following two functions do
303 nothing for registers which live in bank 0. For others, they respectively
304 set the bank register to the correct value (before the register is
305 accessed), and back to 0 (afterwards). */
306static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
307{
308 if (reg & 0xff00) {
309 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
310 outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
311 }
312}
313
314static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
315{
316 if (reg & 0xff00) {
317 outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
318 outb_p(0, client->addr + DATA_REG_OFFSET);
319 }
320}
321
322static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
323{
324 struct w83627ehf_data *data = i2c_get_clientdata(client);
325 int res, word_sized = is_word_sized(reg);
326
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100327 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200328
329 w83627ehf_set_bank(client, reg);
330 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
331 res = inb_p(client->addr + DATA_REG_OFFSET);
332 if (word_sized) {
333 outb_p((reg & 0xff) + 1,
334 client->addr + ADDR_REG_OFFSET);
335 res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
336 }
337 w83627ehf_reset_bank(client, reg);
338
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100339 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200340
341 return res;
342}
343
344static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
345{
346 struct w83627ehf_data *data = i2c_get_clientdata(client);
347 int word_sized = is_word_sized(reg);
348
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100349 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200350
351 w83627ehf_set_bank(client, reg);
352 outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
353 if (word_sized) {
354 outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
355 outb_p((reg & 0xff) + 1,
356 client->addr + ADDR_REG_OFFSET);
357 }
358 outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
359 w83627ehf_reset_bank(client, reg);
360
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100361 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200362 return 0;
363}
364
365/* This function assumes that the caller holds data->update_lock */
366static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
367{
368 struct w83627ehf_data *data = i2c_get_clientdata(client);
369 u8 reg;
370
371 switch (nr) {
372 case 0:
373 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
374 | ((data->fan_div[0] & 0x03) << 4);
Rudolf Marek14992c72006-10-08 22:02:09 +0200375 /* fan5 input control bit is write only, compute the value */
376 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
Jean Delvare08e7e272005-04-25 22:43:25 +0200377 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
378 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
379 | ((data->fan_div[0] & 0x04) << 3);
380 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
381 break;
382 case 1:
383 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
384 | ((data->fan_div[1] & 0x03) << 6);
Rudolf Marek14992c72006-10-08 22:02:09 +0200385 /* fan5 input control bit is write only, compute the value */
386 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
Jean Delvare08e7e272005-04-25 22:43:25 +0200387 w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
388 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
389 | ((data->fan_div[1] & 0x04) << 4);
390 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
391 break;
392 case 2:
393 reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
394 | ((data->fan_div[2] & 0x03) << 6);
395 w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
396 reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
397 | ((data->fan_div[2] & 0x04) << 5);
398 w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
399 break;
400 case 3:
401 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
402 | (data->fan_div[3] & 0x03);
403 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
404 reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
405 | ((data->fan_div[3] & 0x04) << 5);
406 w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
407 break;
408 case 4:
409 reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
Jean Delvare33725ad2007-04-17 00:32:27 -0700410 | ((data->fan_div[4] & 0x03) << 2)
Jean Delvare08e7e272005-04-25 22:43:25 +0200411 | ((data->fan_div[4] & 0x04) << 5);
412 w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
413 break;
414 }
415}
416
417static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
418{
419 struct i2c_client *client = to_i2c_client(dev);
420 struct w83627ehf_data *data = i2c_get_clientdata(client);
Rudolf Marek08c79952006-07-05 18:14:31 +0200421 int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
Jean Delvare08e7e272005-04-25 22:43:25 +0200422 int i;
423
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100424 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200425
426 if (time_after(jiffies, data->last_updated + HZ)
427 || !data->valid) {
428 /* Fan clock dividers */
429 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
430 data->fan_div[0] = (i >> 4) & 0x03;
431 data->fan_div[1] = (i >> 6) & 0x03;
432 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
433 data->fan_div[2] = (i >> 6) & 0x03;
434 i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
435 data->fan_div[0] |= (i >> 3) & 0x04;
436 data->fan_div[1] |= (i >> 4) & 0x04;
437 data->fan_div[2] |= (i >> 5) & 0x04;
438 if (data->has_fan & ((1 << 3) | (1 << 4))) {
439 i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
440 data->fan_div[3] = i & 0x03;
441 data->fan_div[4] = ((i >> 2) & 0x03)
442 | ((i >> 5) & 0x04);
443 }
444 if (data->has_fan & (1 << 3)) {
445 i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
446 data->fan_div[3] |= (i >> 5) & 0x04;
447 }
448
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100449 /* Measured voltages and limits */
David Hubbard657c93b2007-02-14 21:15:04 +0100450 for (i = 0; i < w83627ehf_num_in; i++) {
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100451 data->in[i] = w83627ehf_read_value(client,
452 W83627EHF_REG_IN(i));
453 data->in_min[i] = w83627ehf_read_value(client,
454 W83627EHF_REG_IN_MIN(i));
455 data->in_max[i] = w83627ehf_read_value(client,
456 W83627EHF_REG_IN_MAX(i));
457 }
458
Jean Delvare08e7e272005-04-25 22:43:25 +0200459 /* Measured fan speeds and limits */
460 for (i = 0; i < 5; i++) {
461 if (!(data->has_fan & (1 << i)))
462 continue;
463
464 data->fan[i] = w83627ehf_read_value(client,
465 W83627EHF_REG_FAN[i]);
466 data->fan_min[i] = w83627ehf_read_value(client,
467 W83627EHF_REG_FAN_MIN[i]);
468
469 /* If we failed to measure the fan speed and clock
470 divider can be increased, let's try that for next
471 time */
472 if (data->fan[i] == 0xff
473 && data->fan_div[i] < 0x07) {
Jean Delvare33725ad2007-04-17 00:32:27 -0700474 dev_dbg(&client->dev, "Increasing fan%d "
Jean Delvare08e7e272005-04-25 22:43:25 +0200475 "clock divider from %u to %u\n",
Jean Delvare33725ad2007-04-17 00:32:27 -0700476 i + 1, div_from_reg(data->fan_div[i]),
Jean Delvare08e7e272005-04-25 22:43:25 +0200477 div_from_reg(data->fan_div[i] + 1));
478 data->fan_div[i]++;
479 w83627ehf_write_fan_div(client, i);
480 /* Preserve min limit if possible */
481 if (data->fan_min[i] >= 2
482 && data->fan_min[i] != 255)
483 w83627ehf_write_value(client,
484 W83627EHF_REG_FAN_MIN[i],
485 (data->fan_min[i] /= 2));
486 }
487 }
488
Rudolf Marek08c79952006-07-05 18:14:31 +0200489 for (i = 0; i < 4; i++) {
490 /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
491 if (i != 1) {
492 pwmcfg = w83627ehf_read_value(client,
493 W83627EHF_REG_PWM_ENABLE[i]);
494 tolerance = w83627ehf_read_value(client,
495 W83627EHF_REG_TOLERANCE[i]);
496 }
497 data->pwm_mode[i] =
498 ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
499 ? 0 : 1;
500 data->pwm_enable[i] =
501 ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
502 & 3) + 1;
503 data->pwm[i] = w83627ehf_read_value(client,
504 W83627EHF_REG_PWM[i]);
505 data->fan_min_output[i] = w83627ehf_read_value(client,
506 W83627EHF_REG_FAN_MIN_OUTPUT[i]);
507 data->fan_stop_time[i] = w83627ehf_read_value(client,
508 W83627EHF_REG_FAN_STOP_TIME[i]);
509 data->target_temp[i] =
510 w83627ehf_read_value(client,
511 W83627EHF_REG_TARGET[i]) &
512 (data->pwm_mode[i] == 1 ? 0x7f : 0xff);
513 data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
514 & 0x0f;
515 }
516
Jean Delvare08e7e272005-04-25 22:43:25 +0200517 /* Measured temperatures and limits */
518 data->temp1 = w83627ehf_read_value(client,
519 W83627EHF_REG_TEMP1);
520 data->temp1_max = w83627ehf_read_value(client,
521 W83627EHF_REG_TEMP1_OVER);
522 data->temp1_max_hyst = w83627ehf_read_value(client,
523 W83627EHF_REG_TEMP1_HYST);
524 for (i = 0; i < 2; i++) {
525 data->temp[i] = w83627ehf_read_value(client,
526 W83627EHF_REG_TEMP[i]);
527 data->temp_max[i] = w83627ehf_read_value(client,
528 W83627EHF_REG_TEMP_OVER[i]);
529 data->temp_max_hyst[i] = w83627ehf_read_value(client,
530 W83627EHF_REG_TEMP_HYST[i]);
531 }
532
Jean Delvarea4589db2006-03-23 16:30:29 +0100533 data->alarms = w83627ehf_read_value(client,
534 W83627EHF_REG_ALARM1) |
535 (w83627ehf_read_value(client,
536 W83627EHF_REG_ALARM2) << 8) |
537 (w83627ehf_read_value(client,
538 W83627EHF_REG_ALARM3) << 16);
539
Jean Delvare08e7e272005-04-25 22:43:25 +0200540 data->last_updated = jiffies;
541 data->valid = 1;
542 }
543
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100544 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200545 return data;
546}
547
548/*
549 * Sysfs callback functions
550 */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100551#define show_in_reg(reg) \
552static ssize_t \
553show_##reg(struct device *dev, struct device_attribute *attr, \
554 char *buf) \
555{ \
556 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
557 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
558 int nr = sensor_attr->index; \
559 return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
560}
561show_in_reg(in)
562show_in_reg(in_min)
563show_in_reg(in_max)
564
565#define store_in_reg(REG, reg) \
566static ssize_t \
567store_in_##reg (struct device *dev, struct device_attribute *attr, \
568 const char *buf, size_t count) \
569{ \
570 struct i2c_client *client = to_i2c_client(dev); \
571 struct w83627ehf_data *data = i2c_get_clientdata(client); \
572 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
573 int nr = sensor_attr->index; \
574 u32 val = simple_strtoul(buf, NULL, 10); \
575 \
576 mutex_lock(&data->update_lock); \
577 data->in_##reg[nr] = in_to_reg(val, nr); \
578 w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
579 data->in_##reg[nr]); \
580 mutex_unlock(&data->update_lock); \
581 return count; \
582}
583
584store_in_reg(MIN, min)
585store_in_reg(MAX, max)
586
Jean Delvarea4589db2006-03-23 16:30:29 +0100587static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
588{
589 struct w83627ehf_data *data = w83627ehf_update_device(dev);
590 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
591 int nr = sensor_attr->index;
592 return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01);
593}
594
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100595static struct sensor_device_attribute sda_in_input[] = {
596 SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
597 SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
598 SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
599 SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
600 SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
601 SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
602 SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
603 SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
604 SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
605 SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
606};
607
Jean Delvarea4589db2006-03-23 16:30:29 +0100608static struct sensor_device_attribute sda_in_alarm[] = {
609 SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
610 SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
611 SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
612 SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
613 SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
614 SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21),
615 SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20),
616 SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16),
617 SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17),
618 SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),
619};
620
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100621static struct sensor_device_attribute sda_in_min[] = {
622 SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
623 SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
624 SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
625 SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
626 SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
627 SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
628 SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
629 SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
630 SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
631 SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
632};
633
634static struct sensor_device_attribute sda_in_max[] = {
635 SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
636 SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
637 SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
638 SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
639 SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
640 SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
641 SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
642 SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
643 SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
644 SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
645};
646
Jean Delvare08e7e272005-04-25 22:43:25 +0200647#define show_fan_reg(reg) \
648static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100649show_##reg(struct device *dev, struct device_attribute *attr, \
650 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200651{ \
652 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100653 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
654 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200655 return sprintf(buf, "%d\n", \
656 fan_from_reg(data->reg[nr], \
657 div_from_reg(data->fan_div[nr]))); \
658}
659show_fan_reg(fan);
660show_fan_reg(fan_min);
661
662static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100663show_fan_div(struct device *dev, struct device_attribute *attr,
664 char *buf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200665{
666 struct w83627ehf_data *data = w83627ehf_update_device(dev);
Yuan Mu412fec82006-02-05 23:24:16 +0100667 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
668 int nr = sensor_attr->index;
669 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
Jean Delvare08e7e272005-04-25 22:43:25 +0200670}
671
672static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +0100673store_fan_min(struct device *dev, struct device_attribute *attr,
674 const char *buf, size_t count)
Jean Delvare08e7e272005-04-25 22:43:25 +0200675{
676 struct i2c_client *client = to_i2c_client(dev);
677 struct w83627ehf_data *data = i2c_get_clientdata(client);
Yuan Mu412fec82006-02-05 23:24:16 +0100678 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
679 int nr = sensor_attr->index;
Jean Delvare08e7e272005-04-25 22:43:25 +0200680 unsigned int val = simple_strtoul(buf, NULL, 10);
681 unsigned int reg;
682 u8 new_div;
683
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100684 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200685 if (!val) {
686 /* No min limit, alarm disabled */
687 data->fan_min[nr] = 255;
688 new_div = data->fan_div[nr]; /* No change */
689 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
690 } else if ((reg = 1350000U / val) >= 128 * 255) {
691 /* Speed below this value cannot possibly be represented,
692 even with the highest divider (128) */
693 data->fan_min[nr] = 254;
694 new_div = 7; /* 128 == (1 << 7) */
695 dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
696 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
697 } else if (!reg) {
698 /* Speed above this value cannot possibly be represented,
699 even with the lowest divider (1) */
700 data->fan_min[nr] = 1;
701 new_div = 0; /* 1 == (1 << 0) */
702 dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
Jean Delvareb9110b12005-05-02 23:08:22 +0200703 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
Jean Delvare08e7e272005-04-25 22:43:25 +0200704 } else {
705 /* Automatically pick the best divider, i.e. the one such
706 that the min limit will correspond to a register value
707 in the 96..192 range */
708 new_div = 0;
709 while (reg > 192 && new_div < 7) {
710 reg >>= 1;
711 new_div++;
712 }
713 data->fan_min[nr] = reg;
714 }
715
716 /* Write both the fan clock divider (if it changed) and the new
717 fan min (unconditionally) */
718 if (new_div != data->fan_div[nr]) {
Jean Delvare158ce072007-06-17 16:09:12 +0200719 /* Preserve the fan speed reading */
720 if (data->fan[nr] != 0xff) {
721 if (new_div > data->fan_div[nr])
722 data->fan[nr] >>= new_div - data->fan_div[nr];
723 else if (data->fan[nr] & 0x80)
724 data->fan[nr] = 0xff;
725 else
726 data->fan[nr] <<= data->fan_div[nr] - new_div;
727 }
Jean Delvare08e7e272005-04-25 22:43:25 +0200728
729 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
730 nr + 1, div_from_reg(data->fan_div[nr]),
731 div_from_reg(new_div));
732 data->fan_div[nr] = new_div;
733 w83627ehf_write_fan_div(client, nr);
734 }
735 w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
736 data->fan_min[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100737 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200738
739 return count;
740}
741
Yuan Mu412fec82006-02-05 23:24:16 +0100742static struct sensor_device_attribute sda_fan_input[] = {
743 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
744 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
745 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
746 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
747 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
748};
Jean Delvare08e7e272005-04-25 22:43:25 +0200749
Jean Delvarea4589db2006-03-23 16:30:29 +0100750static struct sensor_device_attribute sda_fan_alarm[] = {
751 SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
752 SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
753 SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
754 SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10),
755 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),
756};
757
Yuan Mu412fec82006-02-05 23:24:16 +0100758static struct sensor_device_attribute sda_fan_min[] = {
759 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
760 store_fan_min, 0),
761 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
762 store_fan_min, 1),
763 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
764 store_fan_min, 2),
765 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
766 store_fan_min, 3),
767 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
768 store_fan_min, 4),
769};
Jean Delvare08e7e272005-04-25 22:43:25 +0200770
Yuan Mu412fec82006-02-05 23:24:16 +0100771static struct sensor_device_attribute sda_fan_div[] = {
772 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
773 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
774 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
775 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
776 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
777};
Jean Delvare08e7e272005-04-25 22:43:25 +0200778
Jean Delvare08e7e272005-04-25 22:43:25 +0200779#define show_temp1_reg(reg) \
780static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700781show_##reg(struct device *dev, struct device_attribute *attr, \
782 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200783{ \
784 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
785 return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
786}
787show_temp1_reg(temp1);
788show_temp1_reg(temp1_max);
789show_temp1_reg(temp1_max_hyst);
790
791#define store_temp1_reg(REG, reg) \
792static ssize_t \
Greg Kroah-Hartman6f637a62005-06-21 21:01:59 -0700793store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
794 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200795{ \
796 struct i2c_client *client = to_i2c_client(dev); \
797 struct w83627ehf_data *data = i2c_get_clientdata(client); \
798 u32 val = simple_strtoul(buf, NULL, 10); \
799 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100800 mutex_lock(&data->update_lock); \
Rudolf Marek08c79952006-07-05 18:14:31 +0200801 data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200802 w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
803 data->temp1_##reg); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100804 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200805 return count; \
806}
807store_temp1_reg(OVER, max);
808store_temp1_reg(HYST, max_hyst);
809
Jean Delvare08e7e272005-04-25 22:43:25 +0200810#define show_temp_reg(reg) \
811static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100812show_##reg(struct device *dev, struct device_attribute *attr, \
813 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200814{ \
815 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Yuan Mu412fec82006-02-05 23:24:16 +0100816 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
817 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200818 return sprintf(buf, "%d\n", \
819 LM75_TEMP_FROM_REG(data->reg[nr])); \
820}
821show_temp_reg(temp);
822show_temp_reg(temp_max);
823show_temp_reg(temp_max_hyst);
824
825#define store_temp_reg(REG, reg) \
826static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +0100827store_##reg(struct device *dev, struct device_attribute *attr, \
828 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +0200829{ \
830 struct i2c_client *client = to_i2c_client(dev); \
831 struct w83627ehf_data *data = i2c_get_clientdata(client); \
Yuan Mu412fec82006-02-05 23:24:16 +0100832 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
833 int nr = sensor_attr->index; \
Jean Delvare08e7e272005-04-25 22:43:25 +0200834 u32 val = simple_strtoul(buf, NULL, 10); \
835 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100836 mutex_lock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200837 data->reg[nr] = LM75_TEMP_TO_REG(val); \
838 w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
839 data->reg[nr]); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100840 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +0200841 return count; \
842}
843store_temp_reg(OVER, temp_max);
844store_temp_reg(HYST, temp_max_hyst);
845
Yuan Mu412fec82006-02-05 23:24:16 +0100846static struct sensor_device_attribute sda_temp[] = {
847 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
848 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
849 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
850 SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
851 store_temp1_max, 0),
852 SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
853 store_temp_max, 0),
854 SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
855 store_temp_max, 1),
856 SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
857 store_temp1_max_hyst, 0),
858 SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
859 store_temp_max_hyst, 0),
860 SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
861 store_temp_max_hyst, 1),
Jean Delvarea4589db2006-03-23 16:30:29 +0100862 SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
863 SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
864 SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
Yuan Mu412fec82006-02-05 23:24:16 +0100865};
Jean Delvare08e7e272005-04-25 22:43:25 +0200866
Rudolf Marek08c79952006-07-05 18:14:31 +0200867#define show_pwm_reg(reg) \
868static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
869 char *buf) \
870{ \
871 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
872 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
873 int nr = sensor_attr->index; \
874 return sprintf(buf, "%d\n", data->reg[nr]); \
875}
876
877show_pwm_reg(pwm_mode)
878show_pwm_reg(pwm_enable)
879show_pwm_reg(pwm)
880
881static ssize_t
882store_pwm_mode(struct device *dev, struct device_attribute *attr,
883 const char *buf, size_t count)
884{
885 struct i2c_client *client = to_i2c_client(dev);
886 struct w83627ehf_data *data = i2c_get_clientdata(client);
887 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
888 int nr = sensor_attr->index;
889 u32 val = simple_strtoul(buf, NULL, 10);
890 u16 reg;
891
892 if (val > 1)
893 return -EINVAL;
894 mutex_lock(&data->update_lock);
895 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
896 data->pwm_mode[nr] = val;
897 reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
898 if (!val)
899 reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
900 w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
901 mutex_unlock(&data->update_lock);
902 return count;
903}
904
905static ssize_t
906store_pwm(struct device *dev, struct device_attribute *attr,
907 const char *buf, size_t count)
908{
909 struct i2c_client *client = to_i2c_client(dev);
910 struct w83627ehf_data *data = i2c_get_clientdata(client);
911 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
912 int nr = sensor_attr->index;
913 u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
914
915 mutex_lock(&data->update_lock);
916 data->pwm[nr] = val;
917 w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val);
918 mutex_unlock(&data->update_lock);
919 return count;
920}
921
922static ssize_t
923store_pwm_enable(struct device *dev, struct device_attribute *attr,
924 const char *buf, size_t count)
925{
926 struct i2c_client *client = to_i2c_client(dev);
927 struct w83627ehf_data *data = i2c_get_clientdata(client);
928 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
929 int nr = sensor_attr->index;
930 u32 val = simple_strtoul(buf, NULL, 10);
931 u16 reg;
932
933 if (!val || (val > 2)) /* only modes 1 and 2 are supported */
934 return -EINVAL;
935 mutex_lock(&data->update_lock);
936 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
937 data->pwm_enable[nr] = val;
938 reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
939 reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
940 w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
941 mutex_unlock(&data->update_lock);
942 return count;
943}
944
945
946#define show_tol_temp(reg) \
947static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
948 char *buf) \
949{ \
950 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
951 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
952 int nr = sensor_attr->index; \
953 return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
954}
955
956show_tol_temp(tolerance)
957show_tol_temp(target_temp)
958
959static ssize_t
960store_target_temp(struct device *dev, struct device_attribute *attr,
961 const char *buf, size_t count)
962{
963 struct i2c_client *client = to_i2c_client(dev);
964 struct w83627ehf_data *data = i2c_get_clientdata(client);
965 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
966 int nr = sensor_attr->index;
967 u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
968
969 mutex_lock(&data->update_lock);
970 data->target_temp[nr] = val;
971 w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val);
972 mutex_unlock(&data->update_lock);
973 return count;
974}
975
976static ssize_t
977store_tolerance(struct device *dev, struct device_attribute *attr,
978 const char *buf, size_t count)
979{
980 struct i2c_client *client = to_i2c_client(dev);
981 struct w83627ehf_data *data = i2c_get_clientdata(client);
982 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
983 int nr = sensor_attr->index;
984 u16 reg;
985 /* Limit the temp to 0C - 15C */
986 u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
987
988 mutex_lock(&data->update_lock);
989 reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]);
990 data->tolerance[nr] = val;
991 if (nr == 1)
992 reg = (reg & 0x0f) | (val << 4);
993 else
994 reg = (reg & 0xf0) | val;
995 w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg);
996 mutex_unlock(&data->update_lock);
997 return count;
998}
999
1000static struct sensor_device_attribute sda_pwm[] = {
1001 SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
1002 SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
1003 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
1004 SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
1005};
1006
1007static struct sensor_device_attribute sda_pwm_mode[] = {
1008 SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1009 store_pwm_mode, 0),
1010 SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1011 store_pwm_mode, 1),
1012 SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1013 store_pwm_mode, 2),
1014 SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1015 store_pwm_mode, 3),
1016};
1017
1018static struct sensor_device_attribute sda_pwm_enable[] = {
1019 SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1020 store_pwm_enable, 0),
1021 SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1022 store_pwm_enable, 1),
1023 SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1024 store_pwm_enable, 2),
1025 SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1026 store_pwm_enable, 3),
1027};
1028
1029static struct sensor_device_attribute sda_target_temp[] = {
1030 SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
1031 store_target_temp, 0),
1032 SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
1033 store_target_temp, 1),
1034 SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
1035 store_target_temp, 2),
1036 SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
1037 store_target_temp, 3),
1038};
1039
1040static struct sensor_device_attribute sda_tolerance[] = {
1041 SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1042 store_tolerance, 0),
1043 SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1044 store_tolerance, 1),
1045 SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1046 store_tolerance, 2),
1047 SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1048 store_tolerance, 3),
1049};
1050
Rudolf Marek08c79952006-07-05 18:14:31 +02001051/* Smart Fan registers */
1052
1053#define fan_functions(reg, REG) \
1054static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1055 char *buf) \
1056{ \
1057 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
1058 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1059 int nr = sensor_attr->index; \
1060 return sprintf(buf, "%d\n", data->reg[nr]); \
1061}\
1062static ssize_t \
1063store_##reg(struct device *dev, struct device_attribute *attr, \
1064 const char *buf, size_t count) \
1065{\
1066 struct i2c_client *client = to_i2c_client(dev); \
1067 struct w83627ehf_data *data = i2c_get_clientdata(client); \
1068 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1069 int nr = sensor_attr->index; \
1070 u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
1071 mutex_lock(&data->update_lock); \
1072 data->reg[nr] = val; \
1073 w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
1074 mutex_unlock(&data->update_lock); \
1075 return count; \
1076}
1077
1078fan_functions(fan_min_output, FAN_MIN_OUTPUT)
1079
1080#define fan_time_functions(reg, REG) \
1081static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1082 char *buf) \
1083{ \
1084 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
1085 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1086 int nr = sensor_attr->index; \
1087 return sprintf(buf, "%d\n", \
1088 step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
1089} \
1090\
1091static ssize_t \
1092store_##reg(struct device *dev, struct device_attribute *attr, \
1093 const char *buf, size_t count) \
1094{ \
1095 struct i2c_client *client = to_i2c_client(dev); \
1096 struct w83627ehf_data *data = i2c_get_clientdata(client); \
1097 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
1098 int nr = sensor_attr->index; \
1099 u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
1100 data->pwm_mode[nr]); \
1101 mutex_lock(&data->update_lock); \
1102 data->reg[nr] = val; \
1103 w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
1104 mutex_unlock(&data->update_lock); \
1105 return count; \
1106} \
1107
1108fan_time_functions(fan_stop_time, FAN_STOP_TIME)
1109
1110
1111static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
1112 SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1113 store_fan_stop_time, 3),
1114 SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1115 store_fan_min_output, 3),
1116};
1117
1118static struct sensor_device_attribute sda_sf3_arrays[] = {
1119 SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1120 store_fan_stop_time, 0),
1121 SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1122 store_fan_stop_time, 1),
1123 SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1124 store_fan_stop_time, 2),
1125 SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1126 store_fan_min_output, 0),
1127 SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1128 store_fan_min_output, 1),
1129 SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
1130 store_fan_min_output, 2),
1131};
1132
Jean Delvare08e7e272005-04-25 22:43:25 +02001133/*
1134 * Driver and client management
1135 */
1136
David Hubbardc18beb52006-09-24 21:04:38 +02001137static void w83627ehf_device_remove_files(struct device *dev)
1138{
1139 /* some entries in the following arrays may not have been used in
1140 * device_create_file(), but device_remove_file() will ignore them */
1141 int i;
1142
1143 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
1144 device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
1145 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
1146 device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
David Hubbard657c93b2007-02-14 21:15:04 +01001147 for (i = 0; i < w83627ehf_num_in; i++) {
David Hubbardc18beb52006-09-24 21:04:38 +02001148 device_remove_file(dev, &sda_in_input[i].dev_attr);
1149 device_remove_file(dev, &sda_in_alarm[i].dev_attr);
1150 device_remove_file(dev, &sda_in_min[i].dev_attr);
1151 device_remove_file(dev, &sda_in_max[i].dev_attr);
1152 }
1153 for (i = 0; i < 5; i++) {
1154 device_remove_file(dev, &sda_fan_input[i].dev_attr);
1155 device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
1156 device_remove_file(dev, &sda_fan_div[i].dev_attr);
1157 device_remove_file(dev, &sda_fan_min[i].dev_attr);
1158 }
1159 for (i = 0; i < 4; i++) {
1160 device_remove_file(dev, &sda_pwm[i].dev_attr);
1161 device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
1162 device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
1163 device_remove_file(dev, &sda_target_temp[i].dev_attr);
1164 device_remove_file(dev, &sda_tolerance[i].dev_attr);
1165 }
1166 for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
1167 device_remove_file(dev, &sda_temp[i].dev_attr);
1168}
1169
Jean Delvare08e7e272005-04-25 22:43:25 +02001170static struct i2c_driver w83627ehf_driver;
1171
1172static void w83627ehf_init_client(struct i2c_client *client)
1173{
1174 int i;
1175 u8 tmp;
1176
1177 /* Start monitoring is needed */
1178 tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
1179 if (!(tmp & 0x01))
1180 w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
1181 tmp | 0x01);
1182
1183 /* Enable temp2 and temp3 if needed */
1184 for (i = 0; i < 2; i++) {
1185 tmp = w83627ehf_read_value(client,
1186 W83627EHF_REG_TEMP_CONFIG[i]);
1187 if (tmp & 0x01)
1188 w83627ehf_write_value(client,
1189 W83627EHF_REG_TEMP_CONFIG[i],
1190 tmp & 0xfe);
1191 }
1192}
1193
Jean Delvare2d8672c2005-07-19 23:56:35 +02001194static int w83627ehf_detect(struct i2c_adapter *adapter)
Jean Delvare08e7e272005-04-25 22:43:25 +02001195{
1196 struct i2c_client *client;
1197 struct w83627ehf_data *data;
Yuan Mu412fec82006-02-05 23:24:16 +01001198 struct device *dev;
Rudolf Marek08c79952006-07-05 18:14:31 +02001199 u8 fan4pin, fan5pin;
Jean Delvare08e7e272005-04-25 22:43:25 +02001200 int i, err = 0;
1201
Jean Delvare1a641fc2007-04-23 14:41:16 -07001202 if (!request_region(address + IOREGION_OFFSET, IOREGION_LENGTH,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001203 w83627ehf_driver.driver.name)) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001204 err = -EBUSY;
1205 goto exit;
1206 }
1207
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001208 if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001209 err = -ENOMEM;
1210 goto exit_release;
1211 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001212
1213 client = &data->client;
1214 i2c_set_clientdata(client, data);
1215 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001216 mutex_init(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +02001217 client->adapter = adapter;
1218 client->driver = &w83627ehf_driver;
1219 client->flags = 0;
Yuan Mu412fec82006-02-05 23:24:16 +01001220 dev = &client->dev;
Jean Delvare08e7e272005-04-25 22:43:25 +02001221
David Hubbard657c93b2007-02-14 21:15:04 +01001222 if (w83627ehf_num_in == 9)
1223 strlcpy(client->name, "w83627dhg", I2C_NAME_SIZE);
1224 else /* just say ehf. 627EHG is 627EHF in lead-free packaging. */
1225 strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
1226
Jean Delvare08e7e272005-04-25 22:43:25 +02001227 data->valid = 0;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001228 mutex_init(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +02001229
1230 /* Tell the i2c layer a new client has arrived */
1231 if ((err = i2c_attach_client(client)))
1232 goto exit_free;
1233
1234 /* Initialize the chip */
1235 w83627ehf_init_client(client);
1236
1237 /* A few vars need to be filled upon startup */
1238 for (i = 0; i < 5; i++)
1239 data->fan_min[i] = w83627ehf_read_value(client,
1240 W83627EHF_REG_FAN_MIN[i]);
1241
Rudolf Marek08c79952006-07-05 18:14:31 +02001242 /* fan4 and fan5 share some pins with the GPIO and serial flash */
1243
1244 superio_enter();
1245 fan5pin = superio_inb(0x24) & 0x2;
1246 fan4pin = superio_inb(0x29) & 0x6;
1247 superio_exit();
1248
Jean Delvare08e7e272005-04-25 22:43:25 +02001249 /* It looks like fan4 and fan5 pins can be alternatively used
Rudolf Marek14992c72006-10-08 22:02:09 +02001250 as fan on/off switches, but fan5 control is write only :/
1251 We assume that if the serial interface is disabled, designers
1252 connected fan5 as input unless they are emitting log 1, which
1253 is not the default. */
Rudolf Marek08c79952006-07-05 18:14:31 +02001254
Jean Delvare08e7e272005-04-25 22:43:25 +02001255 data->has_fan = 0x07; /* fan1, fan2 and fan3 */
1256 i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
Rudolf Marek08c79952006-07-05 18:14:31 +02001257 if ((i & (1 << 2)) && (!fan4pin))
Jean Delvare08e7e272005-04-25 22:43:25 +02001258 data->has_fan |= (1 << 3);
Rudolf Marek14992c72006-10-08 22:02:09 +02001259 if (!(i & (1 << 1)) && (!fan5pin))
Jean Delvare08e7e272005-04-25 22:43:25 +02001260 data->has_fan |= (1 << 4);
1261
1262 /* Register sysfs hooks */
Rudolf Marek08c79952006-07-05 18:14:31 +02001263 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001264 if ((err = device_create_file(dev,
1265 &sda_sf3_arrays[i].dev_attr)))
1266 goto exit_remove;
Rudolf Marek08c79952006-07-05 18:14:31 +02001267
1268 /* if fan4 is enabled create the sf3 files for it */
1269 if (data->has_fan & (1 << 3))
David Hubbardc18beb52006-09-24 21:04:38 +02001270 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
1271 if ((err = device_create_file(dev,
1272 &sda_sf3_arrays_fan4[i].dev_attr)))
1273 goto exit_remove;
1274 }
Rudolf Marek08c79952006-07-05 18:14:31 +02001275
David Hubbard657c93b2007-02-14 21:15:04 +01001276 for (i = 0; i < w83627ehf_num_in; i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001277 if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
1278 || (err = device_create_file(dev,
1279 &sda_in_alarm[i].dev_attr))
1280 || (err = device_create_file(dev,
1281 &sda_in_min[i].dev_attr))
1282 || (err = device_create_file(dev,
1283 &sda_in_max[i].dev_attr)))
1284 goto exit_remove;
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001285
Yuan Mu412fec82006-02-05 23:24:16 +01001286 for (i = 0; i < 5; i++) {
Rudolf Marek08c79952006-07-05 18:14:31 +02001287 if (data->has_fan & (1 << i)) {
David Hubbardc18beb52006-09-24 21:04:38 +02001288 if ((err = device_create_file(dev,
1289 &sda_fan_input[i].dev_attr))
1290 || (err = device_create_file(dev,
1291 &sda_fan_alarm[i].dev_attr))
1292 || (err = device_create_file(dev,
1293 &sda_fan_div[i].dev_attr))
1294 || (err = device_create_file(dev,
1295 &sda_fan_min[i].dev_attr)))
1296 goto exit_remove;
1297 if (i < 4 && /* w83627ehf only has 4 pwm */
1298 ((err = device_create_file(dev,
1299 &sda_pwm[i].dev_attr))
1300 || (err = device_create_file(dev,
1301 &sda_pwm_mode[i].dev_attr))
1302 || (err = device_create_file(dev,
1303 &sda_pwm_enable[i].dev_attr))
1304 || (err = device_create_file(dev,
1305 &sda_target_temp[i].dev_attr))
1306 || (err = device_create_file(dev,
1307 &sda_tolerance[i].dev_attr))))
1308 goto exit_remove;
Rudolf Marek08c79952006-07-05 18:14:31 +02001309 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001310 }
Rudolf Marek08c79952006-07-05 18:14:31 +02001311
Yuan Mu412fec82006-02-05 23:24:16 +01001312 for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
David Hubbardc18beb52006-09-24 21:04:38 +02001313 if ((err = device_create_file(dev, &sda_temp[i].dev_attr)))
1314 goto exit_remove;
1315
1316 data->class_dev = hwmon_device_register(dev);
1317 if (IS_ERR(data->class_dev)) {
1318 err = PTR_ERR(data->class_dev);
1319 goto exit_remove;
1320 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001321
1322 return 0;
1323
David Hubbardc18beb52006-09-24 21:04:38 +02001324exit_remove:
1325 w83627ehf_device_remove_files(dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001326 i2c_detach_client(client);
Jean Delvare08e7e272005-04-25 22:43:25 +02001327exit_free:
1328 kfree(data);
1329exit_release:
Jean Delvare1a641fc2007-04-23 14:41:16 -07001330 release_region(address + IOREGION_OFFSET, IOREGION_LENGTH);
Jean Delvare08e7e272005-04-25 22:43:25 +02001331exit:
1332 return err;
1333}
1334
Jean Delvare08e7e272005-04-25 22:43:25 +02001335static int w83627ehf_detach_client(struct i2c_client *client)
1336{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001337 struct w83627ehf_data *data = i2c_get_clientdata(client);
Jean Delvare08e7e272005-04-25 22:43:25 +02001338 int err;
1339
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001340 hwmon_device_unregister(data->class_dev);
David Hubbardc18beb52006-09-24 21:04:38 +02001341 w83627ehf_device_remove_files(&client->dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001342
Jean Delvare7bef5592005-07-27 22:14:49 +02001343 if ((err = i2c_detach_client(client)))
Jean Delvare08e7e272005-04-25 22:43:25 +02001344 return err;
Jean Delvare1a641fc2007-04-23 14:41:16 -07001345 release_region(client->addr + IOREGION_OFFSET, IOREGION_LENGTH);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001346 kfree(data);
Jean Delvare08e7e272005-04-25 22:43:25 +02001347
1348 return 0;
1349}
1350
1351static struct i2c_driver w83627ehf_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001352 .driver = {
Jean Delvare87218842006-09-03 22:36:14 +02001353 .owner = THIS_MODULE,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001354 .name = "w83627ehf",
1355 },
Jean Delvare2d8672c2005-07-19 23:56:35 +02001356 .attach_adapter = w83627ehf_detect,
Jean Delvare08e7e272005-04-25 22:43:25 +02001357 .detach_client = w83627ehf_detach_client,
1358};
1359
Jean Delvare2d8672c2005-07-19 23:56:35 +02001360static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
Jean Delvare08e7e272005-04-25 22:43:25 +02001361{
1362 u16 val;
1363
1364 REG = sioaddr;
1365 VAL = sioaddr + 1;
1366 superio_enter();
1367
1368 val = (superio_inb(SIO_REG_DEVID) << 8)
1369 | superio_inb(SIO_REG_DEVID + 1);
David Hubbard657c93b2007-02-14 21:15:04 +01001370 switch (val & SIO_ID_MASK) {
1371 case SIO_W83627DHG_ID:
1372 w83627ehf_num_in = 9;
1373 break;
1374 case SIO_W83627EHF_ID:
1375 case SIO_W83627EHG_ID:
1376 w83627ehf_num_in = 10;
1377 break;
1378 default:
1379 printk(KERN_WARNING "w83627ehf: unsupported chip ID: 0x%04x\n",
1380 val);
Jean Delvare08e7e272005-04-25 22:43:25 +02001381 superio_exit();
1382 return -ENODEV;
1383 }
1384
1385 superio_select(W83627EHF_LD_HWM);
1386 val = (superio_inb(SIO_REG_ADDR) << 8)
1387 | superio_inb(SIO_REG_ADDR + 1);
Jean Delvare1a641fc2007-04-23 14:41:16 -07001388 *addr = val & IOREGION_ALIGNMENT;
Jean Delvare2d8672c2005-07-19 23:56:35 +02001389 if (*addr == 0) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001390 superio_exit();
1391 return -ENODEV;
1392 }
1393
1394 /* Activate logical device if needed */
1395 val = superio_inb(SIO_REG_ENABLE);
1396 if (!(val & 0x01))
1397 superio_outb(SIO_REG_ENABLE, val | 0x01);
1398
1399 superio_exit();
1400 return 0;
1401}
1402
1403static int __init sensors_w83627ehf_init(void)
1404{
Jean Delvare2d8672c2005-07-19 23:56:35 +02001405 if (w83627ehf_find(0x2e, &address)
1406 && w83627ehf_find(0x4e, &address))
Jean Delvare08e7e272005-04-25 22:43:25 +02001407 return -ENODEV;
1408
Jean Delvarefde09502005-07-19 23:51:07 +02001409 return i2c_isa_add_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +02001410}
1411
1412static void __exit sensors_w83627ehf_exit(void)
1413{
Jean Delvarefde09502005-07-19 23:51:07 +02001414 i2c_isa_del_driver(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +02001415}
1416
1417MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
1418MODULE_DESCRIPTION("W83627EHF driver");
1419MODULE_LICENSE("GPL");
1420
1421module_init(sensors_w83627ehf_init);
1422module_exit(sensors_w83627ehf_exit);