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