Blame view

drivers/hwmon/w83627hf.c 54.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
      w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
                  monitoring
      Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
      Philip Edelbrock <phil@netroedge.com>,
      and Mark Studebaker <mdsxyz123@yahoo.com>
      Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
787c72b10   Jean Delvare   hwmon/w83627hf: C...
8
      Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  
  /*
      Supports following chips:
  
      Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
      w83627hf	9	3	2	3	0x20	0x5ca3	no	yes(LPC)
      w83627thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
      w83637hf	7	3	3	3	0x80	0x5ca3	no	yes(LPC)
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
32
      w83687thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
39
40
      w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
  
      For other winbond chips, and for i2c support in the above chips,
      use w83781d.c.
  
      Note: automatic ("cruise") fan control for 697, 637 & 627thf not
      supported yet.
  */
18de030f1   Joe Perches   hwmon: (w83627hf)...
41
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
787c72b10   Jean Delvare   hwmon/w83627hf: C...
46
  #include <linux/platform_device.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
47
  #include <linux/hwmon.h>
07584c762   Jim Cromie   hwmon: (w83627hf)...
48
  #include <linux/hwmon-sysfs.h>
303760b44   Jean Delvare   [PATCH] hwmon: hw...
49
  #include <linux/hwmon-vid.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
50
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
51
  #include <linux/mutex.h>
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
52
  #include <linux/ioport.h>
b9acb64a3   Jean Delvare   hwmon: Check for ...
53
  #include <linux/acpi.h>
6055fae8a   H Hartley Sweeten   hwmon: Include <l...
54
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  #include "lm75.h"
787c72b10   Jean Delvare   hwmon/w83627hf: C...
56
  static struct platform_device *pdev;
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
57
58
59
  
  #define DRVNAME "w83627hf"
  enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
60
61
62
63
  struct w83627hf_sio_data {
  	enum chips type;
  	int sioaddr;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
  static u8 force_i2c = 0x1f;
  module_param(force_i2c, byte, 0);
  MODULE_PARM_DESC(force_i2c,
  		 "Initialize the i2c address of the sensors");
90ab5ee94   Rusty Russell   module_param: mak...
68
  static bool init = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  module_param(init, bool, 0);
  MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
67b671bce   Jean Delvare   hwmon: Let the us...
71
72
73
  static unsigned short force_id;
  module_param(force_id, ushort, 0);
  MODULE_PARM_DESC(force_id, "Override the detected device ID");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  /* modified from kernel/include/traps.c */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  #define	DEV	0x07	/* Register: Logical device select */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  
  /* logical device numbers for superio_select (below) */
  #define W83627HF_LD_FDC		0x00
  #define W83627HF_LD_PRT		0x01
  #define W83627HF_LD_UART1	0x02
  #define W83627HF_LD_UART2	0x03
  #define W83627HF_LD_KBC		0x05
  #define W83627HF_LD_CIR		0x06 /* w83627hf only */
  #define W83627HF_LD_GAME	0x07
  #define W83627HF_LD_MIDI	0x07
  #define W83627HF_LD_GPIO1	0x07
  #define W83627HF_LD_GPIO5	0x07 /* w83627thf only */
  #define W83627HF_LD_GPIO2	0x08
  #define W83627HF_LD_GPIO3	0x09
  #define W83627HF_LD_GPIO4	0x09 /* w83627thf only */
  #define W83627HF_LD_ACPI	0x0a
  #define W83627HF_LD_HWM		0x0b
  
  #define	DEVID	0x20	/* Register: Device ID */
  
  #define W83627THF_GPIO5_EN	0x30 /* w83627thf only */
  #define W83627THF_GPIO5_IOSR	0xf3 /* w83627thf only */
  #define W83627THF_GPIO5_DR	0xf4 /* w83627thf only */
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
99
100
101
  #define W83687THF_VID_EN	0x29 /* w83687thf only */
  #define W83687THF_VID_CFG	0xF0 /* w83687thf only */
  #define W83687THF_VID_DATA	0xF1 /* w83687thf only */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  static inline void
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
103
  superio_outb(struct w83627hf_sio_data *sio, int reg, int val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
105
106
  	outb(reg, sio->sioaddr);
  	outb(val, sio->sioaddr + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
  }
  
  static inline int
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
110
  superio_inb(struct w83627hf_sio_data *sio, int reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
112
113
  	outb(reg, sio->sioaddr);
  	return inb(sio->sioaddr + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
  }
  
  static inline void
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
117
  superio_select(struct w83627hf_sio_data *sio, int ld)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
119
120
  	outb(DEV, sio->sioaddr);
  	outb(ld,  sio->sioaddr + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
  }
  
  static inline void
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
124
  superio_enter(struct w83627hf_sio_data *sio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
126
127
  	outb(0x87, sio->sioaddr);
  	outb(0x87, sio->sioaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
  }
  
  static inline void
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
131
  superio_exit(struct w83627hf_sio_data *sio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
133
  	outb(0xAA, sio->sioaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
  }
  
  #define W627_DEVID 0x52
  #define W627THF_DEVID 0x82
  #define W697_DEVID 0x60
  #define W637_DEVID 0x70
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
140
  #define W687THF_DEVID 0x85
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
  #define WINB_ACT_REG 0x30
  #define WINB_BASE_REG 0x60
  /* Constants specified below */
ada0c2f8f   Petr Vandrovec   [PATCH] hwmon: Fi...
144
145
  /* Alignment of the base address */
  #define WINB_ALIGNMENT		~7
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

ada0c2f8f   Petr Vandrovec   [PATCH] hwmon: Fi...
147
148
149
  /* Offset & size of I/O region we are interested in */
  #define WINB_REGION_OFFSET	5
  #define WINB_REGION_SIZE	2
787c72b10   Jean Delvare   hwmon/w83627hf: C...
150
151
152
  /* Where are the sensors address/data registers relative to the region offset */
  #define W83781D_ADDR_REG_OFFSET 0
  #define W83781D_DATA_REG_OFFSET 1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
161
  
  /* The W83781D registers */
  /* The W83782D registers for nr=7,8 are in bank 5 */
  #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
  					   (0x554 + (((nr) - 7) * 2)))
  #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
  					   (0x555 + (((nr) - 7) * 2)))
  #define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
  					   (0x550 + (nr) - 7))
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
162
163
164
  /* nr:0-2 for fans:1-3 */
  #define W83627HF_REG_FAN_MIN(nr)	(0x3b + (nr))
  #define W83627HF_REG_FAN(nr)		(0x28 + (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

df48ed804   Jim Cromie   hwmon: (w83627hf)...
166
167
168
169
170
171
  #define W83627HF_REG_TEMP2_CONFIG 0x152
  #define W83627HF_REG_TEMP3_CONFIG 0x252
  /* these are zero-based, unlike config constants above */
  static const u16 w83627hf_reg_temp[]		= { 0x27, 0x150, 0x250 };
  static const u16 w83627hf_reg_temp_hyst[]	= { 0x3A, 0x153, 0x253 };
  static const u16 w83627hf_reg_temp_over[]	= { 0x39, 0x155, 0x255 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
  
  #define W83781D_REG_BANK 0x4E
  
  #define W83781D_REG_CONFIG 0x40
4a1c4447e   Yuan Mu   [PATCH] hwmon: Fi...
176
177
178
  #define W83781D_REG_ALARM1 0x459
  #define W83781D_REG_ALARM2 0x45A
  #define W83781D_REG_ALARM3 0x45B
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  #define W83781D_REG_BEEP_CONFIG 0x4D
  #define W83781D_REG_BEEP_INTS1 0x56
  #define W83781D_REG_BEEP_INTS2 0x57
  #define W83781D_REG_BEEP_INTS3 0x453
  
  #define W83781D_REG_VID_FANDIV 0x47
  
  #define W83781D_REG_CHIPID 0x49
  #define W83781D_REG_WCHIPID 0x58
  #define W83781D_REG_CHIPMAN 0x4F
  #define W83781D_REG_PIN 0x4B
  
  #define W83781D_REG_VBAT 0x5D
  
  #define W83627HF_REG_PWM1 0x5A
  #define W83627HF_REG_PWM2 0x5B
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196

a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
197
198
199
200
201
202
  static const u8 W83627THF_REG_PWM_ENABLE[] = {
  	0x04,		/* FAN 1 mode */
  	0x04,		/* FAN 2 mode */
  	0x12,		/* FAN AUX mode */
  };
  static const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
203
204
205
  #define W83627THF_REG_PWM1		0x01	/* 697HF/637HF/687THF too */
  #define W83627THF_REG_PWM2		0x03	/* 697HF/637HF/687THF too */
  #define W83627THF_REG_PWM3		0x11	/* 637HF/687THF too */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
207
  #define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF/687THF too */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
  
  static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
  static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
                               W83627THF_REG_PWM3 };
  #define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
07584c762   Jim Cromie   hwmon: (w83627hf)...
213
  				    regpwm_627hf[nr] : regpwm[nr])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
215
216
217
218
219
220
221
222
223
224
225
  #define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
  
  #define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
  #define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
  #define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
  
  static const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
  					W83637HF_REG_PWM_FREQ2,
  					W83637HF_REG_PWM_FREQ3 };
  
  #define W83627HF_BASE_PWM_FREQ	46870
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  #define W83781D_REG_I2C_ADDR 0x48
  #define W83781D_REG_I2C_SUBADDR 0x4A
  
  /* Sensor selection */
  #define W83781D_REG_SCFG1 0x5D
  static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
  #define W83781D_REG_SCFG2 0x59
  static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
  #define W83781D_DEFAULT_BETA 3435
  
  /* Conversions. Limit checking is only done on the TO_REG
     variants. Note that you should be a bit careful with which arguments
     these macros are called: arguments may be evaluated more than once.
     Fixing this is just not worth it. */
  #define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
  #define IN_FROM_REG(val) ((val) * 16)
  
  static inline u8 FAN_TO_REG(long rpm, int div)
  {
  	if (rpm == 0)
  		return 255;
  	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
  	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
  			     254);
  }
  
  #define TEMP_MIN (-128000)
  #define TEMP_MAX ( 127000)
  
  /* TEMP: 0.001C/bit (-128C to +127C)
     REG: 1C/bit, two's complement */
5bfedac04   Christian Hohnstaedt   hwmon: Allow writ...
257
  static u8 TEMP_TO_REG(long temp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  {
          int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
          ntemp += (ntemp<0 ? -500 : 500);
          return (u8)(ntemp / 1000);
  }
  
  static int TEMP_FROM_REG(u8 reg)
  {
          return (s8)reg * 1000;
  }
  
  #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
  
  #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  static inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
  {
  	unsigned long freq;
  	freq = W83627HF_BASE_PWM_FREQ >> reg;
  	return freq;
  }
  static inline u8 pwm_freq_to_reg_627hf(unsigned long val)
  {
  	u8 i;
  	/* Only 5 dividers (1 2 4 8 16)
  	   Search for the nearest available frequency */
  	for (i = 0; i < 4; i++) {
  		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
  			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
  			break;
  	}
  	return i;
  }
  
  static inline unsigned long pwm_freq_from_reg(u8 reg)
  {
  	/* Clock bit 8 -> 180 kHz or 24 MHz */
  	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
  
  	reg &= 0x7f;
  	/* This should not happen but anyway... */
  	if (reg == 0)
  		reg++;
  	return (clock / (reg << 8));
  }
  static inline u8 pwm_freq_to_reg(unsigned long val)
  {
  	/* Minimum divider value is 0x01 and maximum is 0x7F */
  	if (val >= 93750)	/* The highest we can do */
  		return 0x01;
  	if (val >= 720)	/* Use 24 MHz clock */
  		return (24000000UL / (val << 8));
  	if (val < 6)		/* The lowest we can do */
  		return 0xFF;
  	else			/* Use 180 kHz clock */
  		return (0x80 | (180000UL / (val << 8)));
  }
1c1381076   Jean Delvare   hwmon: (w83627hf)...
314
315
  #define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
  #define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
321
322
  
  #define DIV_FROM_REG(val) (1 << (val))
  
  static inline u8 DIV_TO_REG(long val)
  {
  	int i;
  	val = SENSORS_LIMIT(val, 1, 128) >> 1;
abc019224   Grant Coady   [PATCH] I2C: Sett...
323
  	for (i = 0; i < 7; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
  		if (val == 0)
  			break;
  		val >>= 1;
  	}
  	return ((u8) i);
  }
ed6bafbf6   Jean Delvare   hwmon: Cleanup a ...
330
331
  /* For each registered chip, we need to keep some data in memory.
     The structure is dynamically allocated. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  struct w83627hf_data {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
333
334
  	unsigned short addr;
  	const char *name;
1beeffe43   Tony Jones   hwmon: Convert fr...
335
  	struct device *hwmon_dev;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
336
  	struct mutex lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  	enum chips type;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
338
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
  	u8 in[9];		/* Register value */
  	u8 in_max[9];		/* Register value */
  	u8 in_min[9];		/* Register value */
  	u8 fan[3];		/* Register value */
  	u8 fan_min[3];		/* Register value */
df48ed804   Jim Cromie   hwmon: (w83627hf)...
346
347
348
  	u16 temp[3];		/* Register value */
  	u16 temp_max[3];	/* Register value */
  	u16 temp_max_hyst[3];	/* Register value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
  	u8 fan_div[3];		/* Register encoding, shifted right */
  	u8 vid;			/* Register encoding, combined */
  	u32 alarms;		/* Register encoding, combined */
  	u32 beep_mask;		/* Register encoding, combined */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  	u8 pwm[3];		/* Register value */
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
354
355
356
  	u8 pwm_enable[3];	/* 1 = manual
  				   2 = thermal cruise (also called SmartFan I)
  				   3 = fan speed cruise */
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
357
  	u8 pwm_freq[3];		/* Register value */
b26f93309   Jean Delvare   hwmon: Don't expo...
358
359
  	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
  				   4 = thermistor */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  	u8 vrm;
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
361
  	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363

787c72b10   Jean Delvare   hwmon/w83627hf: C...
364
  static int w83627hf_probe(struct platform_device *pdev);
d05461289   Jean Delvare   hwmon: Add missin...
365
  static int __devexit w83627hf_remove(struct platform_device *pdev);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
366
367
368
  
  static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
  static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
c09c5184a   Jean Delvare   hwmon: (w83627hf)...
369
  static void w83627hf_update_fan_div(struct w83627hf_data *data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  static struct w83627hf_data *w83627hf_update_device(struct device *dev);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
371
  static void w83627hf_init_device(struct platform_device *pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372

787c72b10   Jean Delvare   hwmon/w83627hf: C...
373
  static struct platform_driver w83627hf_driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
374
  	.driver = {
872188420   Jean Delvare   i2c-isa: Restore ...
375
  		.owner	= THIS_MODULE,
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
376
  		.name	= DRVNAME,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
377
  	},
787c72b10   Jean Delvare   hwmon/w83627hf: C...
378
379
  	.probe		= w83627hf_probe,
  	.remove		= __devexit_p(w83627hf_remove),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
  };
07584c762   Jim Cromie   hwmon: (w83627hf)...
381
382
383
384
385
386
387
  static ssize_t
  show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", (long)IN_FROM_REG(data->in[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  static ssize_t
  show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", (long)IN_FROM_REG(data->in_min[nr]));
  }
  static ssize_t
  show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", (long)IN_FROM_REG(data->in_max[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
405
406
407
408
409
410
411
  static ssize_t
  store_in_min(struct device *dev, struct device_attribute *devattr,
  	     const char *buf, size_t count)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	long val = simple_strtol(buf, NULL, 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412

07584c762   Jim Cromie   hwmon: (w83627hf)...
413
414
415
416
417
418
419
420
421
422
423
424
425
  	mutex_lock(&data->update_lock);
  	data->in_min[nr] = IN_TO_REG(val);
  	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  static ssize_t
  store_in_max(struct device *dev, struct device_attribute *devattr,
  	     const char *buf, size_t count)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	long val = simple_strtol(buf, NULL, 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426

07584c762   Jim Cromie   hwmon: (w83627hf)...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  	mutex_lock(&data->update_lock);
  	data->in_max[nr] = IN_TO_REG(val);
  	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  #define sysfs_vin_decl(offset) \
  static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
  			  show_in_input, NULL, offset);		\
  static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
  			  show_in_min, store_in_min, offset);	\
  static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
  			  show_in_max, store_in_max, offset);
  
  sysfs_vin_decl(1);
  sysfs_vin_decl(2);
  sysfs_vin_decl(3);
  sysfs_vin_decl(4);
  sysfs_vin_decl(5);
  sysfs_vin_decl(6);
  sysfs_vin_decl(7);
  sysfs_vin_decl(8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
453
454
455
  
  /* use a different set of functions for in0 */
  static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
  {
  	long in0;
  
  	if ((data->vrm_ovt & 0x01) &&
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
456
457
  		(w83627thf == data->type || w83637hf == data->type
  		 || w83687thf == data->type))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
466
467
  
  		/* use VRM9 calculation */
  		in0 = (long)((reg * 488 + 70000 + 50) / 100);
  	else
  		/* use VRM8 (standard) calculation */
  		in0 = (long)IN_FROM_REG(reg);
  
  	return sprintf(buf,"%ld
  ", in0);
  }
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
468
  static ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return show_in_0(data, buf, data->in[0]);
  }
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
473
  static ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return show_in_0(data, buf, data->in_min[0]);
  }
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
478
  static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
481
482
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return show_in_0(data, buf, data->in_max[0]);
  }
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
483
  static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
  	const char *buf, size_t count)
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
486
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
  	u32 val;
  
  	val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
490
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
  	
  	if ((data->vrm_ovt & 0x01) &&
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
493
494
  		(w83627thf == data->type || w83637hf == data->type
  		 || w83687thf == data->type))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
  
  		/* use VRM9 calculation */
2723ab91c   Yuan Mu   [PATCH] hwmon: Fi...
497
498
499
  		data->in_min[0] =
  			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
  					255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
  	else
  		/* use VRM8 (standard) calculation */
  		data->in_min[0] = IN_TO_REG(val);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
503
  	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
504
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
  	return count;
  }
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
507
  static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
  	const char *buf, size_t count)
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
510
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
  	u32 val;
  
  	val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
514
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  
  	if ((data->vrm_ovt & 0x01) &&
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
517
518
  		(w83627thf == data->type || w83637hf == data->type
  		 || w83687thf == data->type))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
  		
  		/* use VRM9 calculation */
2723ab91c   Yuan Mu   [PATCH] hwmon: Fi...
521
522
523
  		data->in_max[0] =
  			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
  					255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
  	else
  		/* use VRM8 (standard) calculation */
  		data->in_max[0] = IN_TO_REG(val);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
527
  	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
528
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
534
535
536
  	return count;
  }
  
  static DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
  static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
  	show_regs_in_min0, store_regs_in_min0);
  static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
  	show_regs_in_max0, store_regs_in_max0);
07584c762   Jim Cromie   hwmon: (w83627hf)...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  static ssize_t
  show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", FAN_FROM_REG(data->fan[nr],
  				(long)DIV_FROM_REG(data->fan_div[nr])));
  }
  static ssize_t
  show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", FAN_FROM_REG(data->fan_min[nr],
  				(long)DIV_FROM_REG(data->fan_div[nr])));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
556
557
  store_fan_min(struct device *dev, struct device_attribute *devattr,
  	      const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
559
  	int nr = to_sensor_dev_attr(devattr)->index;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
560
  	struct w83627hf_data *data = dev_get_drvdata(dev);
07584c762   Jim Cromie   hwmon: (w83627hf)...
561
  	u32 val = simple_strtoul(buf, NULL, 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
563
  	mutex_lock(&data->update_lock);
07584c762   Jim Cromie   hwmon: (w83627hf)...
564
  	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
565
  	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
07584c762   Jim Cromie   hwmon: (w83627hf)...
566
  			     data->fan_min[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
568
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
  	return count;
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
571
572
573
574
575
  #define sysfs_fan_decl(offset)	\
  static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
  			  show_fan_input, NULL, offset - 1);		\
  static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
  			  show_fan_min, store_fan_min, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576

07584c762   Jim Cromie   hwmon: (w83627hf)...
577
578
579
  sysfs_fan_decl(1);
  sysfs_fan_decl(2);
  sysfs_fan_decl(3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580

07584c762   Jim Cromie   hwmon: (w83627hf)...
581
582
583
584
585
  static ssize_t
  show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
586
587
588
589
590
  
  	u16 tmp = data->temp[nr];
  	return sprintf(buf, "%ld
  ", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
  					  : (long) TEMP_FROM_REG(tmp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592

07584c762   Jim Cromie   hwmon: (w83627hf)...
593
594
595
596
597
598
  static ssize_t
  show_temp_max(struct device *dev, struct device_attribute *devattr,
  	      char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
599
600
601
602
603
  
  	u16 tmp = data->temp_max[nr];
  	return sprintf(buf, "%ld
  ", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
  					  : (long) TEMP_FROM_REG(tmp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

07584c762   Jim Cromie   hwmon: (w83627hf)...
606
607
608
609
610
611
  static ssize_t
  show_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
  		   char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
612
613
614
615
616
  
  	u16 tmp = data->temp_max_hyst[nr];
  	return sprintf(buf, "%ld
  ", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
  					  : (long) TEMP_FROM_REG(tmp));
07584c762   Jim Cromie   hwmon: (w83627hf)...
617
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618

07584c762   Jim Cromie   hwmon: (w83627hf)...
619
620
621
622
623
624
625
  static ssize_t
  store_temp_max(struct device *dev, struct device_attribute *devattr,
  	       const char *buf, size_t count)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	long val = simple_strtol(buf, NULL, 10);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
626
  	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

07584c762   Jim Cromie   hwmon: (w83627hf)...
628
  	mutex_lock(&data->update_lock);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
629
630
  	data->temp_max[nr] = tmp;
  	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
07584c762   Jim Cromie   hwmon: (w83627hf)...
631
632
633
634
635
636
637
638
639
640
641
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  static ssize_t
  store_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
  		    const char *buf, size_t count)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	long val = simple_strtol(buf, NULL, 10);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
642
  	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
07584c762   Jim Cromie   hwmon: (w83627hf)...
643
644
  
  	mutex_lock(&data->update_lock);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
645
646
  	data->temp_max_hyst[nr] = tmp;
  	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
07584c762   Jim Cromie   hwmon: (w83627hf)...
647
648
649
650
651
652
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  #define sysfs_temp_decl(offset) \
  static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
df48ed804   Jim Cromie   hwmon: (w83627hf)...
653
  			  show_temp, NULL, offset - 1);			\
07584c762   Jim Cromie   hwmon: (w83627hf)...
654
  static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
df48ed804   Jim Cromie   hwmon: (w83627hf)...
655
  			  show_temp_max, store_temp_max, offset - 1);	\
07584c762   Jim Cromie   hwmon: (w83627hf)...
656
  static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
df48ed804   Jim Cromie   hwmon: (w83627hf)...
657
  			  show_temp_max_hyst, store_temp_max_hyst, offset - 1);
07584c762   Jim Cromie   hwmon: (w83627hf)...
658
659
660
661
  
  sysfs_temp_decl(1);
  sysfs_temp_decl(2);
  sysfs_temp_decl(3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
  static ssize_t
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
664
  show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", (long) vid_from_reg(data->vid, data->vrm));
  }
  static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
  
  static ssize_t
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
673
  show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  {
90d6619a9   Jean Delvare   hwmon: VRM is not...
675
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
  	return sprintf(buf, "%ld
  ", (long) data->vrm);
  }
  static ssize_t
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
680
  store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
682
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
685
686
687
688
689
690
  	u32 val;
  
  	val = simple_strtoul(buf, NULL, 10);
  	data->vrm = val;
  
  	return count;
  }
  static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
  
  static ssize_t
a5099cfc2   Yani Ioannou   [PATCH] Driver Co...
693
  show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
699
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ", (long) data->alarms);
  }
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700

e3604c626   Jean Delvare   hwmon: (w83627hf)...
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
  static ssize_t
  show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	return sprintf(buf, "%u
  ", (data->alarms >> bitnr) & 1);
  }
  static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
  static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
  static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
  static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
  static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
  static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
  static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
  static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
  static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
  static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
1c1381076   Jean Delvare   hwmon: (w83627hf)...
724
725
726
727
728
729
730
  static ssize_t
  show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ",
  		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
  
  static ssize_t
1c1381076   Jean Delvare   hwmon: (w83627hf)...
734
735
  store_beep_mask(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
737
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1c1381076   Jean Delvare   hwmon: (w83627hf)...
738
  	unsigned long val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
  
  	val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
741
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742

1c1381076   Jean Delvare   hwmon: (w83627hf)...
743
744
745
746
747
748
749
  	/* preserve beep enable */
  	data->beep_mask = (data->beep_mask & 0x8000)
  			| BEEP_MASK_TO_REG(val);
  	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
  			    data->beep_mask & 0xff);
  	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
  			    ((data->beep_mask) >> 16) & 0xff);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
750
  	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
1c1381076   Jean Delvare   hwmon: (w83627hf)...
751
  			    (data->beep_mask >> 8) & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
753
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
  	return count;
  }
1c1381076   Jean Delvare   hwmon: (w83627hf)...
756
757
  static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
  		   show_beep_mask, store_beep_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  static ssize_t
e3604c626   Jean Delvare   hwmon: (w83627hf)...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  show_beep(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	return sprintf(buf, "%u
  ", (data->beep_mask >> bitnr) & 1);
  }
  
  static ssize_t
  store_beep(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	unsigned long bit;
  	u8 reg;
  
  	bit = simple_strtoul(buf, NULL, 10);
  	if (bit & ~1)
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
  	if (bit)
  		data->beep_mask |= (1 << bitnr);
  	else
  		data->beep_mask &= ~(1 << bitnr);
  
  	if (bitnr < 8) {
  		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
  		if (bit)
  			reg |= (1 << bitnr);
  		else
  			reg &= ~(1 << bitnr);
  		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
  	} else if (bitnr < 16) {
  		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
  		if (bit)
  			reg |= (1 << (bitnr - 8));
  		else
  			reg &= ~(1 << (bitnr - 8));
  		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
  	} else {
  		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
  		if (bit)
  			reg |= (1 << (bitnr - 16));
  		else
  			reg &= ~(1 << (bitnr - 16));
  		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
  	}
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
  
  static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 0);
  static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 1);
  static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 2);
  static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 3);
  static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 8);
  static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 9);
  static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 10);
  static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 16);
  static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 17);
  static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 6);
  static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 7);
  static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 11);
  static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 4);
  static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 5);
  static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 13);
1c1381076   Jean Delvare   hwmon: (w83627hf)...
844
845
  static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
  			show_beep, store_beep, 15);
e3604c626   Jean Delvare   hwmon: (w83627hf)...
846
847
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
848
  show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
850
  	int nr = to_sensor_dev_attr(devattr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%ld
  ",
07584c762   Jim Cromie   hwmon: (w83627hf)...
854
  		       (long) DIV_FROM_REG(data->fan_div[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  /* Note: we save and restore the fan minimum here, because its value is
     determined in part by the fan divisor.  This follows the principle of
d6e05edc5   Andreas Mohr   spelling fixes
858
     least surprise; the user doesn't expect the fan minimum to change just
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
     because the divisor changed. */
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
861
862
  store_fan_div(struct device *dev, struct device_attribute *devattr,
  	      const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
864
  	int nr = to_sensor_dev_attr(devattr)->index;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
865
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
867
868
  	unsigned long min;
  	u8 reg;
  	unsigned long val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
869
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
871
872
873
874
875
  
  	/* Save fan_min */
  	min = FAN_FROM_REG(data->fan_min[nr],
  			   DIV_FROM_REG(data->fan_div[nr]));
  
  	data->fan_div[nr] = DIV_TO_REG(val);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
876
  	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
878
  	       & (nr==0 ? 0xcf : 0x3f))
  	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
787c72b10   Jean Delvare   hwmon/w83627hf: C...
879
  	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880

787c72b10   Jean Delvare   hwmon/w83627hf: C...
881
  	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
  	       & ~(1 << (5 + nr)))
  	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
787c72b10   Jean Delvare   hwmon/w83627hf: C...
884
  	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
  
  	/* Restore fan_min */
  	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
888
  	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
890
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
  	return count;
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
893
894
895
896
897
898
  static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
  			  show_fan_div, store_fan_div, 0);
  static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
  			  show_fan_div, store_fan_div, 1);
  static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
  			  show_fan_div, store_fan_div, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
901
  show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
903
  	int nr = to_sensor_dev_attr(devattr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
  	struct w83627hf_data *data = w83627hf_update_device(dev);
07584c762   Jim Cromie   hwmon: (w83627hf)...
905
906
  	return sprintf(buf, "%ld
  ", (long) data->pwm[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
908
909
  }
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
910
911
  store_pwm(struct device *dev, struct device_attribute *devattr,
  	  const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
913
  	int nr = to_sensor_dev_attr(devattr)->index;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
914
  	struct w83627hf_data *data = dev_get_drvdata(dev);
07584c762   Jim Cromie   hwmon: (w83627hf)...
915
  	u32 val = simple_strtoul(buf, NULL, 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
917
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
920
  
  	if (data->type == w83627thf) {
  		/* bits 0-3 are reserved  in 627THF */
07584c762   Jim Cromie   hwmon: (w83627hf)...
921
  		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
922
  		w83627hf_write_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
  				     W836X7HF_REG_PWM(data->type, nr),
07584c762   Jim Cromie   hwmon: (w83627hf)...
924
  				     data->pwm[nr] |
787c72b10   Jean Delvare   hwmon/w83627hf: C...
925
  				     (w83627hf_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
  				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
  	} else {
07584c762   Jim Cromie   hwmon: (w83627hf)...
928
  		data->pwm[nr] = PWM_TO_REG(val);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
929
  		w83627hf_write_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  				     W836X7HF_REG_PWM(data->type, nr),
07584c762   Jim Cromie   hwmon: (w83627hf)...
931
  				     data->pwm[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
933
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
  	return count;
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
936
937
938
  static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
  static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
  static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  static ssize_t
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	return sprintf(buf, "%d
  ", data->pwm_enable[nr]);
  }
  
  static ssize_t
  store_pwm_enable(struct device *dev, struct device_attribute *devattr,
  	  const char *buf, size_t count)
  {
  	int nr = to_sensor_dev_attr(devattr)->index;
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	unsigned long val = simple_strtoul(buf, NULL, 10);
  	u8 reg;
  
  	if (!val || (val > 3))	/* modes 1, 2 and 3 are supported */
  		return -EINVAL;
  	mutex_lock(&data->update_lock);
  	data->pwm_enable[nr] = val;
  	reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
  	reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
  	reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
  	w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
  						  store_pwm_enable, 0);
  static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
  						  store_pwm_enable, 1);
  static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
  						  store_pwm_enable, 2);
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
978
  show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
979
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
980
  	int nr = to_sensor_dev_attr(devattr)->index;
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
981
982
983
984
  	struct w83627hf_data *data = w83627hf_update_device(dev);
  	if (data->type == w83627hf)
  		return sprintf(buf, "%ld
  ",
07584c762   Jim Cromie   hwmon: (w83627hf)...
985
  			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
986
987
988
  	else
  		return sprintf(buf, "%ld
  ",
07584c762   Jim Cromie   hwmon: (w83627hf)...
989
  			pwm_freq_from_reg(data->pwm_freq[nr]));
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
990
991
992
  }
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
993
994
  store_pwm_freq(struct device *dev, struct device_attribute *devattr,
  	       const char *buf, size_t count)
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
995
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
996
  	int nr = to_sensor_dev_attr(devattr)->index;
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
997
998
999
1000
1001
1002
1003
1004
1005
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  	static const u8 mask[]={0xF8, 0x8F};
  	u32 val;
  
  	val = simple_strtoul(buf, NULL, 10);
  
  	mutex_lock(&data->update_lock);
  
  	if (data->type == w83627hf) {
07584c762   Jim Cromie   hwmon: (w83627hf)...
1006
  		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1007
  		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1008
  				(data->pwm_freq[nr] << (nr*4)) |
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1009
  				(w83627hf_read_value(data,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1010
  				W83627HF_REG_PWM_FREQ) & mask[nr]));
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1011
  	} else {
07584c762   Jim Cromie   hwmon: (w83627hf)...
1012
1013
1014
  		data->pwm_freq[nr] = pwm_freq_to_reg(val);
  		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
  				data->pwm_freq[nr]);
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1015
1016
1017
1018
1019
  	}
  
  	mutex_unlock(&data->update_lock);
  	return count;
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
1020
1021
1022
1023
1024
1025
  static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
  			  show_pwm_freq, store_pwm_freq, 0);
  static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
  			  show_pwm_freq, store_pwm_freq, 1);
  static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
  			  show_pwm_freq, store_pwm_freq, 2);
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1026
1027
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
1028
1029
  show_temp_type(struct device *dev, struct device_attribute *devattr,
  	       char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
1031
  	int nr = to_sensor_dev_attr(devattr)->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  	struct w83627hf_data *data = w83627hf_update_device(dev);
07584c762   Jim Cromie   hwmon: (w83627hf)...
1033
1034
  	return sprintf(buf, "%ld
  ", (long) data->sens[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
1036
1037
  }
  
  static ssize_t
07584c762   Jim Cromie   hwmon: (w83627hf)...
1038
1039
  store_temp_type(struct device *dev, struct device_attribute *devattr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  {
07584c762   Jim Cromie   hwmon: (w83627hf)...
1041
  	int nr = to_sensor_dev_attr(devattr)->index;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1042
  	struct w83627hf_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
  	u32 val, tmp;
  
  	val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1046
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
1049
  
  	switch (val) {
  	case 1:		/* PII/Celeron diode */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1050
1051
  		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
  		w83627hf_write_value(data, W83781D_REG_SCFG1,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1052
  				    tmp | BIT_SCFG1[nr]);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1053
1054
  		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
  		w83627hf_write_value(data, W83781D_REG_SCFG2,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1055
1056
  				    tmp | BIT_SCFG2[nr]);
  		data->sens[nr] = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
1058
  		break;
  	case 2:		/* 3904 */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1059
1060
  		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
  		w83627hf_write_value(data, W83781D_REG_SCFG1,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1061
  				    tmp | BIT_SCFG1[nr]);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1062
1063
  		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
  		w83627hf_write_value(data, W83781D_REG_SCFG2,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1064
1065
  				    tmp & ~BIT_SCFG2[nr]);
  		data->sens[nr] = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  		break;
b26f93309   Jean Delvare   hwmon: Don't expo...
1067
1068
1069
1070
1071
1072
  	case W83781D_DEFAULT_BETA:
  		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
  			 "instead
  ", W83781D_DEFAULT_BETA);
  		/* fall through */
  	case 4:		/* thermistor */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1073
1074
  		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
  		w83627hf_write_value(data, W83781D_REG_SCFG1,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1075
1076
  				    tmp & ~BIT_SCFG1[nr]);
  		data->sens[nr] = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
1078
  		break;
  	default:
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1079
  		dev_err(dev,
b26f93309   Jean Delvare   hwmon: Don't expo...
1080
1081
1082
  		       "Invalid sensor type %ld; must be 1, 2, or 4
  ",
  		       (long) val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
  		break;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1085
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
  	return count;
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
1088
1089
1090
  #define sysfs_temp_type(offset) \
  static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
  			  show_temp_type, store_temp_type, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091

07584c762   Jim Cromie   hwmon: (w83627hf)...
1092
1093
1094
  sysfs_temp_type(1);
  sysfs_temp_type(2);
  sysfs_temp_type(3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095

07584c762   Jim Cromie   hwmon: (w83627hf)...
1096
1097
  static ssize_t
  show_name(struct device *dev, struct device_attribute *devattr, char *buf)
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
  {
  	struct w83627hf_data *data = dev_get_drvdata(dev);
  
  	return sprintf(buf, "%s
  ", data->name);
  }
  static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
  
  static int __init w83627hf_find(int sioaddr, unsigned short *addr,
  				struct w83627hf_sio_data *sio_data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  {
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1109
  	int err = -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
  	u16 val;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1111
1112
1113
1114
1115
1116
1117
  	static const __initdata char *names[] = {
  		"W83627HF",
  		"W83627THF",
  		"W83697HF",
  		"W83637HF",
  		"W83687THF",
  	};
c46c0e918   Christian Schulte   hwmon: (w83627hf)...
1118
  	sio_data->sioaddr = sioaddr;
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1119
1120
  	superio_enter(sio_data);
  	val = force_id ? force_id : superio_inb(sio_data, DEVID);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  	switch (val) {
  	case W627_DEVID:
  		sio_data->type = w83627hf;
  		break;
  	case W627THF_DEVID:
  		sio_data->type = w83627thf;
  		break;
  	case W697_DEVID:
  		sio_data->type = w83697hf;
  		break;
  	case W637_DEVID:
  		sio_data->type = w83637hf;
  		break;
  	case W687THF_DEVID:
  		sio_data->type = w83687thf;
  		break;
e142e2a30   Jean Delvare   hwmon/w83627hf: B...
1137
1138
  	case 0xff:	/* No device at all */
  		goto exit;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1139
  	default:
e142e2a30   Jean Delvare   hwmon/w83627hf: B...
1140
1141
  		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)
  ", val);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1142
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
  	}
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1144
1145
1146
  	superio_select(sio_data, W83627HF_LD_HWM);
  	val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
  	       superio_inb(sio_data, WINB_BASE_REG + 1);
ada0c2f8f   Petr Vandrovec   [PATCH] hwmon: Fi...
1147
  	*addr = val & WINB_ALIGNMENT;
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1148
  	if (*addr == 0) {
18de030f1   Joe Perches   hwmon: (w83627hf)...
1149
1150
  		pr_warn("Base address not set, skipping
  ");
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1151
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153

b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1154
  	val = superio_inb(sio_data, WINB_ACT_REG);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1155
  	if (!(val & 0x01)) {
18de030f1   Joe Perches   hwmon: (w83627hf)...
1156
1157
  		pr_warn("Enabling HWM logical device
  ");
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1158
  		superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1159
1160
1161
  	}
  
  	err = 0;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1162
1163
1164
  	pr_info(DRVNAME ": Found %s chip at %#x
  ",
  		names[sio_data->type], *addr);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1165
1166
  
   exit:
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1167
  	superio_exit(sio_data);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1168
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  }
07584c762   Jim Cromie   hwmon: (w83627hf)...
1170
1171
1172
  #define VIN_UNIT_ATTRS(_X_)	\
  	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
  	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1173
1174
1175
  	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
  	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
  	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
07584c762   Jim Cromie   hwmon: (w83627hf)...
1176
1177
1178
1179
  
  #define FAN_UNIT_ATTRS(_X_)	\
  	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
  	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1180
1181
1182
  	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
  	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
  	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
07584c762   Jim Cromie   hwmon: (w83627hf)...
1183
1184
1185
1186
1187
  
  #define TEMP_UNIT_ATTRS(_X_)	\
  	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
  	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
  	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1188
1189
1190
  	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
  	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
  	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
07584c762   Jim Cromie   hwmon: (w83627hf)...
1191

c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1192
1193
1194
1195
  static struct attribute *w83627hf_attributes[] = {
  	&dev_attr_in0_input.attr,
  	&dev_attr_in0_min.attr,
  	&dev_attr_in0_max.attr,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1196
1197
  	&sensor_dev_attr_in0_alarm.dev_attr.attr,
  	&sensor_dev_attr_in0_beep.dev_attr.attr,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
  	VIN_UNIT_ATTRS(2),
  	VIN_UNIT_ATTRS(3),
  	VIN_UNIT_ATTRS(4),
  	VIN_UNIT_ATTRS(7),
  	VIN_UNIT_ATTRS(8),
  
  	FAN_UNIT_ATTRS(1),
  	FAN_UNIT_ATTRS(2),
  
  	TEMP_UNIT_ATTRS(1),
  	TEMP_UNIT_ATTRS(2),
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1209
1210
  
  	&dev_attr_alarms.attr,
1c1381076   Jean Delvare   hwmon: (w83627hf)...
1211
  	&sensor_dev_attr_beep_enable.dev_attr.attr,
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1212
  	&dev_attr_beep_mask.attr,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1213
1214
  	&sensor_dev_attr_pwm1.dev_attr.attr,
  	&sensor_dev_attr_pwm2.dev_attr.attr,
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1215
  	&dev_attr_name.attr,
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1216
1217
1218
1219
1220
1221
1222
1223
  	NULL
  };
  
  static const struct attribute_group w83627hf_group = {
  	.attrs = w83627hf_attributes,
  };
  
  static struct attribute *w83627hf_attributes_opt[] = {
07584c762   Jim Cromie   hwmon: (w83627hf)...
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
  	VIN_UNIT_ATTRS(1),
  	VIN_UNIT_ATTRS(5),
  	VIN_UNIT_ATTRS(6),
  
  	FAN_UNIT_ATTRS(3),
  	TEMP_UNIT_ATTRS(3),
  	&sensor_dev_attr_pwm3.dev_attr.attr,
  
  	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
  	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
  	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
1235
1236
1237
1238
  
  	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
  	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
  	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1239
1240
1241
1242
1243
1244
  	NULL
  };
  
  static const struct attribute_group w83627hf_group_opt = {
  	.attrs = w83627hf_attributes_opt,
  };
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1245
  static int __devinit w83627hf_probe(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1247
1248
  	struct device *dev = &pdev->dev;
  	struct w83627hf_sio_data *sio_data = dev->platform_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  	struct w83627hf_data *data;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1250
  	struct resource *res;
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
1251
  	int err, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
  	static const char *names[] = {
  		"w83627hf",
  		"w83627thf",
  		"w83697hf",
  		"w83637hf",
  		"w83687thf",
  	};
  
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
  		dev_err(dev, "Failed to request region 0x%lx-0x%lx
  ",
  			(unsigned long)res->start,
  			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
  		err = -EBUSY;
  		goto ERROR0;
  	}
ba9c2e8d1   Deepak Saxena   [PATCH] hwmon: kz...
1270
  	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
  		err = -ENOMEM;
  		goto ERROR1;
  	}
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1274
1275
1276
  	data->addr = res->start;
  	data->type = sio_data->type;
  	data->name = names[sio_data->type];
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1277
  	mutex_init(&data->lock);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1278
  	mutex_init(&data->update_lock);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1279
  	platform_set_drvdata(pdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
  	/* Initialize the chip */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1282
  	w83627hf_init_device(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1283
1284
  
  	/* A few vars need to be filled upon startup */
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
1285
1286
1287
  	for (i = 0; i <= 2; i++)
  		data->fan_min[i] = w83627hf_read_value(
  					data, W83627HF_REG_FAN_MIN(i));
c09c5184a   Jean Delvare   hwmon: (w83627hf)...
1288
  	w83627hf_update_fan_div(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289

c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1290
  	/* Register common device attributes */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1291
  	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1292
  		goto ERROR3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293

c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1294
  	/* Register chip-specific device attributes */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1295
  	if (data->type == w83627hf || data->type == w83697hf)
07584c762   Jim Cromie   hwmon: (w83627hf)...
1296
1297
1298
1299
1300
1301
1302
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_in5_input.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in5_min.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in5_max.dev_attr))
  		 || (err = device_create_file(dev,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1303
1304
1305
1306
  				&sensor_dev_attr_in5_alarm.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in5_beep.dev_attr))
  		 || (err = device_create_file(dev,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1307
1308
1309
1310
1311
1312
  				&sensor_dev_attr_in6_input.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in6_min.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in6_max.dev_attr))
  		 || (err = device_create_file(dev,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1313
1314
1315
1316
  				&sensor_dev_attr_in6_alarm.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in6_beep.dev_attr))
  		 || (err = device_create_file(dev,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1317
1318
1319
  				&sensor_dev_attr_pwm1_freq.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_pwm2_freq.dev_attr)))
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1320
  			goto ERROR4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1322
  	if (data->type != w83697hf)
07584c762   Jim Cromie   hwmon: (w83627hf)...
1323
1324
1325
1326
1327
1328
1329
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_in1_input.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in1_min.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in1_max.dev_attr))
  		 || (err = device_create_file(dev,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1330
1331
1332
1333
  				&sensor_dev_attr_in1_alarm.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_in1_beep.dev_attr))
  		 || (err = device_create_file(dev,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1334
1335
1336
1337
1338
1339
  				&sensor_dev_attr_fan3_input.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_fan3_min.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_fan3_div.dev_attr))
  		 || (err = device_create_file(dev,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1340
1341
1342
1343
  				&sensor_dev_attr_fan3_alarm.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_fan3_beep.dev_attr))
  		 || (err = device_create_file(dev,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1344
1345
1346
1347
1348
1349
  				&sensor_dev_attr_temp3_input.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_temp3_max.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_temp3_max_hyst.dev_attr))
  		 || (err = device_create_file(dev,
e3604c626   Jean Delvare   hwmon: (w83627hf)...
1350
1351
1352
1353
  				&sensor_dev_attr_temp3_alarm.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_temp3_beep.dev_attr))
  		 || (err = device_create_file(dev,
07584c762   Jim Cromie   hwmon: (w83627hf)...
1354
  				&sensor_dev_attr_temp3_type.dev_attr)))
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1355
  			goto ERROR4;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1356
  	if (data->type != w83697hf && data->vid != 0xff) {
8a665a055   Jean Delvare   hwmon: Only call ...
1357
1358
  		/* Convert VID to voltage based on VRM */
  		data->vrm = vid_which_vrm();
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1359
1360
  		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
  		 || (err = device_create_file(dev, &dev_attr_vrm)))
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1361
  			goto ERROR4;
8a665a055   Jean Delvare   hwmon: Only call ...
1362
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1364
1365
  	if (data->type == w83627thf || data->type == w83637hf
  	 || data->type == w83687thf)
07584c762   Jim Cromie   hwmon: (w83627hf)...
1366
1367
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_pwm3.dev_attr)))
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1368
  			goto ERROR4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369

1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1370
  	if (data->type == w83637hf || data->type == w83687thf)
07584c762   Jim Cromie   hwmon: (w83627hf)...
1371
1372
1373
1374
1375
1376
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_pwm1_freq.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_pwm2_freq.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_pwm3_freq.dev_attr)))
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1377
  			goto ERROR4;
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
  	if (data->type != w83627hf)
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_pwm1_enable.dev_attr))
  		 || (err = device_create_file(dev,
  				&sensor_dev_attr_pwm2_enable.dev_attr)))
  			goto ERROR4;
  
  	if (data->type == w83627thf || data->type == w83637hf
  	 || data->type == w83687thf)
  		if ((err = device_create_file(dev,
  				&sensor_dev_attr_pwm3_enable.dev_attr)))
  			goto ERROR4;
1beeffe43   Tony Jones   hwmon: Convert fr...
1390
1391
1392
  	data->hwmon_dev = hwmon_device_register(dev);
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1393
1394
  		goto ERROR4;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
  
  	return 0;
c1685f61b   Mark M. Hoffman   hwmon: Fix unchec...
1397
        ERROR4:
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1398
1399
  	sysfs_remove_group(&dev->kobj, &w83627hf_group);
  	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1400
        ERROR3:
04a6217df   Jean Delvare   hwmon: Fix a pote...
1401
  	platform_set_drvdata(pdev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
1403
  	kfree(data);
        ERROR1:
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1404
  	release_region(res->start, WINB_REGION_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
1407
        ERROR0:
  	return err;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1408
  static int __devexit w83627hf_remove(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1410
1411
  	struct w83627hf_data *data = platform_get_drvdata(pdev);
  	struct resource *res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412

1beeffe43   Tony Jones   hwmon: Convert fr...
1413
  	hwmon_device_unregister(data->hwmon_dev);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1414

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1415
1416
  	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
  	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
04a6217df   Jean Delvare   hwmon: Fix a pote...
1417
  	platform_set_drvdata(pdev, NULL);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1418
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1420
1421
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	release_region(res->start, WINB_REGION_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1422
1423
  	return 0;
  }
d58df9cd7   Jean Delvare   hwmon: (w83627hf)...
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
  /* Registers 0x50-0x5f are banked */
  static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
  {
  	if ((reg & 0x00f0) == 0x50) {
  		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
  		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
  	}
  }
  
  /* Not strictly necessary, but play it safe for now */
  static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
  {
  	if (reg & 0xff00) {
  		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
  		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
  	}
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1441
  static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
  	int res, word_sized;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1444
  	mutex_lock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
1446
1447
1448
1449
  	word_sized = (((reg & 0xff00) == 0x100)
  		   || ((reg & 0xff00) == 0x200))
  		  && (((reg & 0x00ff) == 0x50)
  		   || ((reg & 0x00ff) == 0x53)
  		   || ((reg & 0x00ff) == 0x55));
d58df9cd7   Jean Delvare   hwmon: (w83627hf)...
1450
  	w83627hf_set_bank(data, reg);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1451
1452
  	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
  	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
1454
  	if (word_sized) {
  		outb_p((reg & 0xff) + 1,
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1455
  		       data->addr + W83781D_ADDR_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
  		res =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1457
  		    (res << 8) + inb_p(data->addr +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
1459
  				       W83781D_DATA_REG_OFFSET);
  	}
d58df9cd7   Jean Delvare   hwmon: (w83627hf)...
1460
  	w83627hf_reset_bank(data, reg);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1461
  	mutex_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
  	return res;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1464
  static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1466
  	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
  	int res = 0xff, sel;
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1468
1469
  	superio_enter(sio_data);
  	superio_select(sio_data, W83627HF_LD_GPIO5);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
1471
  
  	/* Make sure these GPIO pins are enabled */
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1472
  	if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1473
1474
  		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
1476
1477
1478
1479
  		goto exit;
  	}
  
  	/* Make sure the pins are configured for input
  	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1480
  	sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  	if ((sel & 0x1f) != 0x1f) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1482
  		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
1486
  			"function
  ");
  		goto exit;
  	}
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1487
1488
  	dev_info(&pdev->dev, "Reading VID from GPIO5
  ");
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1489
  	res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
1491
  
  exit:
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1492
  	superio_exit(sio_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493
1494
  	return res;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1495
  static int __devinit w83687thf_read_vid(struct platform_device *pdev)
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1496
  {
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1497
  	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1498
  	int res = 0xff;
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1499
1500
  	superio_enter(sio_data);
  	superio_select(sio_data, W83627HF_LD_HWM);
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1501
1502
  
  	/* Make sure these GPIO pins are enabled */
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1503
  	if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1504
1505
  		dev_dbg(&pdev->dev, "VID disabled, no VID function
  ");
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1506
1507
1508
1509
  		goto exit;
  	}
  
  	/* Make sure the pins are configured for input */
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1510
  	if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1511
  		dev_dbg(&pdev->dev, "VID configured as output, "
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1512
1513
1514
1515
  			"no VID function
  ");
  		goto exit;
  	}
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1516
  	res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1517
1518
  
  exit:
b72656dbc   Jean Delvare   hwmon: (w83627hf)...
1519
  	superio_exit(sio_data);
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1520
1521
  	return res;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1522
  static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  	int word_sized;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1525
  	mutex_lock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
1527
1528
1529
  	word_sized = (((reg & 0xff00) == 0x100)
  		   || ((reg & 0xff00) == 0x200))
  		  && (((reg & 0x00ff) == 0x53)
  		   || ((reg & 0x00ff) == 0x55));
d58df9cd7   Jean Delvare   hwmon: (w83627hf)...
1530
  	w83627hf_set_bank(data, reg);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1531
  	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1532
1533
  	if (word_sized) {
  		outb_p(value >> 8,
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1534
  		       data->addr + W83781D_DATA_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1535
  		outb_p((reg & 0xff) + 1,
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1536
  		       data->addr + W83781D_ADDR_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
1538
  	}
  	outb_p(value & 0xff,
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1539
  	       data->addr + W83781D_DATA_REG_OFFSET);
d58df9cd7   Jean Delvare   hwmon: (w83627hf)...
1540
  	w83627hf_reset_bank(data, reg);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1541
  	mutex_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
1543
  	return 0;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1544
  static void __devinit w83627hf_init_device(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1546
  	struct w83627hf_data *data = platform_get_drvdata(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1547
  	int i;
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1548
  	enum chips type = data->type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
  	u8 tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
1552
  	/* Minimize conflicts with other winbond i2c-only clients...  */
  	/* disable i2c subclients... how to disable main i2c client?? */
  	/* force i2c address to relatively uncommon address */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1553
1554
  	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
  	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555
1556
  
  	/* Read VID only once */
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1557
  	if (type == w83627hf || type == w83637hf) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1558
1559
  		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
  		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
  		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1561
  	} else if (type == w83627thf) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1562
  		data->vid = w83627thf_read_gpio5(pdev);
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1563
  	} else if (type == w83687thf) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1564
  		data->vid = w83687thf_read_vid(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565
1566
1567
  	}
  
  	/* Read VRM & OVT Config only once */
d27c37c0b   Jean Delvare   hwmon/w83627hf: P...
1568
  	if (type == w83627thf || type == w83637hf || type == w83687thf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
  		data->vrm_ovt = 
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1570
  			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
  	}
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1572
  	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
1574
  	for (i = 1; i <= 3; i++) {
  		if (!(tmp & BIT_SCFG1[i - 1])) {
b26f93309   Jean Delvare   hwmon: Don't expo...
1575
  			data->sens[i - 1] = 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
1577
  		} else {
  			if (w83627hf_read_value
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1578
  			    (data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
  			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
  				data->sens[i - 1] = 1;
  			else
  				data->sens[i - 1] = 2;
  		}
  		if ((type == w83697hf) && (i == 2))
  			break;
  	}
  
  	if(init) {
  		/* Enable temp2 */
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1590
  		tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
  		if (tmp & 0x01) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1592
  			dev_warn(&pdev->dev, "Enabling temp2, readings "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
  				 "might not make sense
  ");
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1595
  			w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
1597
1598
1599
1600
  				tmp & 0xfe);
  		}
  
  		/* Enable temp3 */
  		if (type != w83697hf) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1601
  			tmp = w83627hf_read_value(data,
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1602
  				W83627HF_REG_TEMP3_CONFIG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
  			if (tmp & 0x01) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1604
  				dev_warn(&pdev->dev, "Enabling temp3, "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
1606
  					 "readings might not make sense
  ");
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1607
  				w83627hf_write_value(data,
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1608
  					W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611
1612
1613
  	}
  
  	/* Start monitoring */
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1614
1615
  	w83627hf_write_value(data, W83781D_REG_CONFIG,
  			    (w83627hf_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
1617
  						W83781D_REG_CONFIG) & 0xf7)
  			    | 0x01);
ef878b11b   Jean Delvare   hwmon: (w83627hf)...
1618
1619
1620
1621
1622
  
  	/* Enable VBAT monitoring if needed */
  	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
  	if (!(tmp & 0x01))
  		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
  }
c09c5184a   Jean Delvare   hwmon: (w83627hf)...
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
  static void w83627hf_update_fan_div(struct w83627hf_data *data)
  {
  	int reg;
  
  	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
  	data->fan_div[0] = (reg >> 4) & 0x03;
  	data->fan_div[1] = (reg >> 6) & 0x03;
  	if (data->type != w83697hf) {
  		data->fan_div[2] = (w83627hf_read_value(data,
  				       W83781D_REG_PIN) >> 6) & 0x03;
  	}
  	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
  	data->fan_div[0] |= (reg >> 3) & 0x04;
  	data->fan_div[1] |= (reg >> 4) & 0x04;
  	if (data->type != w83697hf)
  		data->fan_div[2] |= (reg >> 5) & 0x04;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
1642
  static struct w83627hf_data *w83627hf_update_device(struct device *dev)
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1643
  	struct w83627hf_data *data = dev_get_drvdata(dev);
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1644
  	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
1645
  	int num_pwms = (data->type == w83697hf) ? 2 : 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1647
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
1649
1650
1651
1652
1653
  
  	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
  	    || !data->valid) {
  		for (i = 0; i <= 8; i++) {
  			/* skip missing sensors */
  			if (((data->type == w83697hf) && (i == 1)) ||
c2db6ce14   Jean Delvare   [PATCH] hwmon: Ad...
1654
  			    ((data->type != w83627hf && data->type != w83697hf)
4a1c4447e   Yuan Mu   [PATCH] hwmon: Fi...
1655
  			    && (i == 5 || i == 6)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
1657
  				continue;
  			data->in[i] =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1658
  			    w83627hf_read_value(data, W83781D_REG_IN(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659
  			data->in_min[i] =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1660
  			    w83627hf_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
1662
  					       W83781D_REG_IN_MIN(i));
  			data->in_max[i] =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1663
  			    w83627hf_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
  					       W83781D_REG_IN_MAX(i));
  		}
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
1666
1667
1668
1669
  		for (i = 0; i <= 2; i++) {
  			data->fan[i] =
  			    w83627hf_read_value(data, W83627HF_REG_FAN(i));
  			data->fan_min[i] =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1670
  			    w83627hf_read_value(data,
2ca2fcd12   Jim Cromie   hwmon: (w83627hf)...
1671
  					       W83627HF_REG_FAN_MIN(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
  		}
07584c762   Jim Cromie   hwmon: (w83627hf)...
1673
  		for (i = 0; i <= 2; i++) {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1674
  			u8 tmp = w83627hf_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
1676
1677
1678
  				W836X7HF_REG_PWM(data->type, i));
   			/* bits 0-3 are reserved  in 627THF */
   			if (data->type == w83627thf)
  				tmp &= 0xf0;
07584c762   Jim Cromie   hwmon: (w83627hf)...
1679
1680
1681
  			data->pwm[i] = tmp;
  			if (i == 1 &&
  			    (data->type == w83627hf || data->type == w83697hf))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
  				break;
  		}
1550cb6d7   Carlos Olalla Martinez   hwmon/w83627hf: A...
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  		if (data->type == w83627hf) {
  				u8 tmp = w83627hf_read_value(data,
  						W83627HF_REG_PWM_FREQ);
  				data->pwm_freq[0] = tmp & 0x07;
  				data->pwm_freq[1] = (tmp >> 4) & 0x07;
  		} else if (data->type != w83627thf) {
  			for (i = 1; i <= 3; i++) {
  				data->pwm_freq[i - 1] =
  					w83627hf_read_value(data,
  						W83637HF_REG_PWM_FREQ[i - 1]);
  				if (i == 2 && (data->type == w83697hf))
  					break;
  			}
  		}
a95a5ed85   Dominik Geyer   hwmon: (w83627hf)...
1698
1699
1700
1701
1702
1703
1704
1705
1706
  		if (data->type != w83627hf) {
  			for (i = 0; i < num_pwms; i++) {
  				u8 tmp = w83627hf_read_value(data,
  					W83627THF_REG_PWM_ENABLE[i]);
  				data->pwm_enable[i] =
  					((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
  					& 0x03) + 1;
  			}
  		}
df48ed804   Jim Cromie   hwmon: (w83627hf)...
1707
1708
1709
1710
1711
1712
1713
  		for (i = 0; i < num_temps; i++) {
  			data->temp[i] = w83627hf_read_value(
  						data, w83627hf_reg_temp[i]);
  			data->temp_max[i] = w83627hf_read_value(
  						data, w83627hf_reg_temp_over[i]);
  			data->temp_max_hyst[i] = w83627hf_read_value(
  						data, w83627hf_reg_temp_hyst[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  		}
c09c5184a   Jean Delvare   hwmon: (w83627hf)...
1715
  		w83627hf_update_fan_div(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716
  		data->alarms =
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1717
1718
1719
1720
  		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
  		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
  		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
  		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
1c1381076   Jean Delvare   hwmon: (w83627hf)...
1721
  		data->beep_mask = (i << 8) |
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1722
1723
  		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
  		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
1725
1726
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1727
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
1729
1730
  
  	return data;
  }
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
  static int __init w83627hf_device_add(unsigned short address,
  				      const struct w83627hf_sio_data *sio_data)
  {
  	struct resource res = {
  		.start	= address + WINB_REGION_OFFSET,
  		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
  		.name	= DRVNAME,
  		.flags	= IORESOURCE_IO,
  	};
  	int err;
b9acb64a3   Jean Delvare   hwmon: Check for ...
1741
1742
1743
  	err = acpi_check_resource_conflict(&res);
  	if (err)
  		goto exit;
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1744
1745
1746
  	pdev = platform_device_alloc(DRVNAME, address);
  	if (!pdev) {
  		err = -ENOMEM;
18de030f1   Joe Perches   hwmon: (w83627hf)...
1747
1748
  		pr_err("Device allocation failed
  ");
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1749
1750
1751
1752
1753
  		goto exit;
  	}
  
  	err = platform_device_add_resources(pdev, &res, 1);
  	if (err) {
18de030f1   Joe Perches   hwmon: (w83627hf)...
1754
1755
  		pr_err("Device resource addition failed (%d)
  ", err);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1756
1757
  		goto exit_device_put;
  	}
2df6d8115   Jean Delvare   hwmon: Use platfo...
1758
1759
1760
  	err = platform_device_add_data(pdev, sio_data,
  				       sizeof(struct w83627hf_sio_data));
  	if (err) {
18de030f1   Joe Perches   hwmon: (w83627hf)...
1761
1762
  		pr_err("Platform data allocation failed
  ");
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1763
1764
  		goto exit_device_put;
  	}
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1765
1766
1767
  
  	err = platform_device_add(pdev);
  	if (err) {
18de030f1   Joe Perches   hwmon: (w83627hf)...
1768
1769
  		pr_err("Device addition failed (%d)
  ", err);
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
  		goto exit_device_put;
  	}
  
  	return 0;
  
  exit_device_put:
  	platform_device_put(pdev);
  exit:
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
  static int __init sensors_w83627hf_init(void)
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1782
1783
1784
1785
1786
1787
  	int err;
  	unsigned short address;
  	struct w83627hf_sio_data sio_data;
  
  	if (w83627hf_find(0x2e, &address, &sio_data)
  	 && w83627hf_find(0x4e, &address, &sio_data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789

787c72b10   Jean Delvare   hwmon/w83627hf: C...
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
  	err = platform_driver_register(&w83627hf_driver);
  	if (err)
  		goto exit;
  
  	/* Sets global pdev as a side effect */
  	err = w83627hf_device_add(address, &sio_data);
  	if (err)
  		goto exit_driver;
  
  	return 0;
  
  exit_driver:
  	platform_driver_unregister(&w83627hf_driver);
  exit:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
1806
1807
1808
  }
  
  static void __exit sensors_w83627hf_exit(void)
  {
787c72b10   Jean Delvare   hwmon/w83627hf: C...
1809
1810
  	platform_device_unregister(pdev);
  	platform_driver_unregister(&w83627hf_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
  }
  
  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
  	      "Philip Edelbrock <phil@netroedge.com>, "
  	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
  MODULE_DESCRIPTION("W83627HF driver");
  MODULE_LICENSE("GPL");
  
  module_init(sensors_w83627hf_init);
  module_exit(sensors_w83627hf_exit);