Blame view

drivers/hwmon/it87.c 67.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *  it87.c - Part of lm_sensors, Linux kernel modules for hardware
   *           monitoring.
   *
   *  The IT8705F is an LPC-based Super I/O part that contains UARTs, a
   *  parallel port, an IR port, a MIDI port, a floppy controller, etc., in
   *  addition to an Environment Controller (Enhanced Hardware Monitor and
   *  Fan Controller)
   *
   *  This driver supports only the Environment Controller in the IT8705F and
   *  similar parts.  The other devices are supported by different drivers.
   *
   *  Supports: IT8705F  Super I/O chip w/LPC interface
   *            IT8712F  Super I/O chip w/LPC interface
   *            IT8716F  Super I/O chip w/LPC interface
   *            IT8718F  Super I/O chip w/LPC interface
   *            IT8720F  Super I/O chip w/LPC interface
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
18
   *            IT8721F  Super I/O chip w/LPC interface
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
19
   *            IT8726F  Super I/O chip w/LPC interface
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
20
   *            IT8758E  Super I/O chip w/LPC interface
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   *            Sis950   A clone of the IT8705F
   *
   *  Copyright (C) 2001 Chris Gauthron
   *  Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org>
   *
   *  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.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

a8ca10379   Joe Perches   hwmon: (it87) Use...
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>
b74f3fdd9   corentin.labbe   hwmon: convert it...
46
  #include <linux/platform_device.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
47
  #include <linux/hwmon.h>
303760b44   Jean Delvare   [PATCH] hwmon: hw...
48
49
  #include <linux/hwmon-sysfs.h>
  #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>
87808be4f   Jean Delvare   Fix unchecked ret...
52
  #include <linux/sysfs.h>
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
53
54
  #include <linux/string.h>
  #include <linux/dmi.h>
b9acb64a3   Jean Delvare   hwmon: Check for ...
55
  #include <linux/acpi.h>
6055fae8a   H Hartley Sweeten   hwmon: Include <l...
56
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

b74f3fdd9   corentin.labbe   hwmon: convert it...
58
  #define DRVNAME "it87"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
60
  enum chips { it87, it8712, it8716, it8718, it8720, it8721 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61

67b671bce   Jean Delvare   hwmon: Let the us...
62
63
64
  static unsigned short force_id;
  module_param(force_id, ushort, 0);
  MODULE_PARM_DESC(force_id, "Override the detected device ID");
b74f3fdd9   corentin.labbe   hwmon: convert it...
65
  static struct platform_device *pdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
  #define	REG	0x2e	/* The register to read/write */
  #define	DEV	0x07	/* Register: Logical device select */
  #define	VAL	0x2f	/* The value to read/write */
  #define PME	0x04	/* The device with the fan registers in it */
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
70
71
72
  
  /* The device with the IT8718F/IT8720F VID value in it */
  #define GPIO	0x07
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
  #define	DEVID	0x20	/* Register: Device ID */
  #define	DEVREV	0x22	/* Register: Device Revision */
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
75
  static inline int superio_inb(int reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
  {
  	outb(reg, REG);
  	return inb(VAL);
  }
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
80
  static inline void superio_outb(int reg, int val)
436cad2a4   Jean Delvare   hwmon: (it87) Fix...
81
82
83
84
  {
  	outb(reg, REG);
  	outb(val, VAL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
90
91
92
93
  static int superio_inw(int reg)
  {
  	int val;
  	outb(reg++, REG);
  	val = inb(VAL) << 8;
  	outb(reg, REG);
  	val |= inb(VAL);
  	return val;
  }
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
94
  static inline void superio_select(int ldn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  {
  	outb(DEV, REG);
87673dd73   Jean Delvare   it87: Add support...
97
  	outb(ldn, VAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  }
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
99
  static inline int superio_enter(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  {
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
101
102
103
104
105
  	/*
  	 * Try to reserve REG and REG + 1 for exclusive access.
  	 */
  	if (!request_muxed_region(REG, 2, DRVNAME))
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
  	outb(0x87, REG);
  	outb(0x01, REG);
  	outb(0x55, REG);
  	outb(0x55, REG);
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
110
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
112
  static inline void superio_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
  {
  	outb(0x02, REG);
  	outb(0x02, VAL);
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
116
  	release_region(REG, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  }
87673dd73   Jean Delvare   it87: Add support...
118
  /* Logical device 4 registers */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
  #define IT8712F_DEVID 0x8712
  #define IT8705F_DEVID 0x8705
17d648bf5   Jean Delvare   it87: Add support...
121
  #define IT8716F_DEVID 0x8716
87673dd73   Jean Delvare   it87: Add support...
122
  #define IT8718F_DEVID 0x8718
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
123
  #define IT8720F_DEVID 0x8720
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
124
  #define IT8721F_DEVID 0x8721
08a8f6e9e   Rudolf Marek   hwmon/it87: Add I...
125
  #define IT8726F_DEVID 0x8726
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  #define IT87_ACT_REG  0x30
  #define IT87_BASE_REG 0x60
87673dd73   Jean Delvare   it87: Add support...
128
  /* Logical device 7 registers (IT8712F and later) */
895ff2676   Jean Delvare   hwmon: (it87) Ver...
129
  #define IT87_SIO_GPIO3_REG	0x27
591ec6509   Jean Delvare   hwmon: (it87) Che...
130
  #define IT87_SIO_GPIO5_REG	0x29
87673dd73   Jean Delvare   it87: Add support...
131
132
  #define IT87_SIO_PINX2_REG	0x2c	/* Pin selection */
  #define IT87_SIO_VID_REG	0xfc	/* VID value */
d9b327c31   Jean Delvare   hwmon: (it87) Add...
133
  #define IT87_SIO_BEEP_PIN_REG	0xf6	/* Beep pin mapping */
87673dd73   Jean Delvare   it87: Add support...
134

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  /* Update battery voltage after every reading if true */
90ab5ee94   Rusty Russell   module_param: mak...
136
  static bool update_vbat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  
  /* Not all BIOSes properly configure the PWM registers */
90ab5ee94   Rusty Russell   module_param: mak...
139
  static bool fix_pwm_polarity;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
  /* Many IT87 constants specified below */
  
  /* Length of ISA address segment */
  #define IT87_EXTENT 8
87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
145
146
147
148
149
150
151
152
153
  /* Length of ISA address segment for Environmental Controller */
  #define IT87_EC_EXTENT 2
  
  /* Offset of EC registers from ISA base address */
  #define IT87_EC_OFFSET 5
  
  /* Where are the ISA address/data registers relative to the EC base address */
  #define IT87_ADDR_REG_OFFSET 0
  #define IT87_DATA_REG_OFFSET 1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
161
  
  /*----- The IT87 registers -----*/
  
  #define IT87_REG_CONFIG        0x00
  
  #define IT87_REG_ALARM1        0x01
  #define IT87_REG_ALARM2        0x02
  #define IT87_REG_ALARM3        0x03
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
162
163
  /* The IT8718F and IT8720F have the VID value in a different register, in
     Super-I/O configuration space. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  #define IT87_REG_VID           0x0a
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
165
166
167
  /* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
     for fan divisors. Later IT8712F revisions must use 16-bit tachometer
     mode. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  #define IT87_REG_FAN_DIV       0x0b
17d648bf5   Jean Delvare   it87: Add support...
169
  #define IT87_REG_FAN_16BIT     0x0c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
  
  /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
172
173
174
175
  static const u8 IT87_REG_FAN[]		= { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
  static const u8 IT87_REG_FAN_MIN[]	= { 0x10, 0x11, 0x12, 0x84, 0x86 };
  static const u8 IT87_REG_FANX[]		= { 0x18, 0x19, 0x1a, 0x81, 0x83 };
  static const u8 IT87_REG_FANX_MIN[]	= { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
  #define IT87_REG_FAN_MAIN_CTRL 0x13
  #define IT87_REG_FAN_CTL       0x14
  #define IT87_REG_PWM(nr)       (0x15 + (nr))
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
179
  #define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
186
187
  
  #define IT87_REG_VIN(nr)       (0x20 + (nr))
  #define IT87_REG_TEMP(nr)      (0x29 + (nr))
  
  #define IT87_REG_VIN_MAX(nr)   (0x30 + (nr) * 2)
  #define IT87_REG_VIN_MIN(nr)   (0x31 + (nr) * 2)
  #define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
  #define IT87_REG_TEMP_LOW(nr)  (0x41 + (nr) * 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  #define IT87_REG_VIN_ENABLE    0x50
  #define IT87_REG_TEMP_ENABLE   0x51
d9b327c31   Jean Delvare   hwmon: (it87) Add...
190
  #define IT87_REG_BEEP_ENABLE   0x5c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  
  #define IT87_REG_CHIPID        0x58
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
193
194
  #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
  #define IT87_REG_AUTO_PWM(nr, i)  (0x65 + (nr) * 8 + (i))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

b74f3fdd9   corentin.labbe   hwmon: convert it...
196
197
198
  struct it87_sio_data {
  	enum chips type;
  	/* Values read from Super-I/O config space */
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
199
  	u8 revision;
b74f3fdd9   corentin.labbe   hwmon: convert it...
200
  	u8 vid_value;
d9b327c31   Jean Delvare   hwmon: (it87) Add...
201
  	u8 beep_pin;
738e5e053   Jean Delvare   hwmon: (it87) Exp...
202
  	u8 internal;	/* Internal sensors can be labeled */
591ec6509   Jean Delvare   hwmon: (it87) Che...
203
  	/* Features skipped based on config or DMI */
895ff2676   Jean Delvare   hwmon: (it87) Ver...
204
  	u8 skip_vid;
591ec6509   Jean Delvare   hwmon: (it87) Che...
205
  	u8 skip_fan;
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
206
  	u8 skip_pwm;
b74f3fdd9   corentin.labbe   hwmon: convert it...
207
  };
ed6bafbf6   Jean Delvare   hwmon: Cleanup a ...
208
209
  /* 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
210
  struct it87_data {
1beeffe43   Tony Jones   hwmon: Convert fr...
211
  	struct device *hwmon_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	enum chips type;
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
213
  	u8 revision;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

b74f3fdd9   corentin.labbe   hwmon: convert it...
215
216
  	unsigned short addr;
  	const char *name;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
217
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
220
  	u16 in_scaled;		/* Internal voltage sensors are scaled */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  	u8 in[9];		/* Register value */
3543a53f6   Jean Delvare   it87: in8 has no ...
222
223
  	u8 in_max[8];		/* Register value */
  	u8 in_min[8];		/* Register value */
9060f8bdd   Jean Delvare   it87: No sysfs fi...
224
  	u8 has_fan;		/* Bitfield, fans enabled */
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
225
226
  	u16 fan[5];		/* Register values, possibly combined */
  	u16 fan_min[5];		/* Register values, possibly combined */
e267d2500   Jean Delvare   hwmon: (it87) Pro...
227
228
229
  	s8 temp[3];		/* Register value */
  	s8 temp_high[3];	/* Register value */
  	s8 temp_low[3];		/* Register value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  	u8 sensor;		/* Register value */
  	u8 fan_div[3];		/* Register encoding, shifted right */
  	u8 vid;			/* Register encoding, combined */
a7be58a12   Jean Delvare   [PATCH] hwmon: it...
233
  	u8 vrm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	u32 alarms;		/* Register encoding, combined */
d9b327c31   Jean Delvare   hwmon: (it87) Add...
235
  	u8 beeps;		/* Register encoding */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	u8 fan_main_ctrl;	/* Register value */
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
237
  	u8 fan_ctl;		/* Register value */
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
238

6229cdb23   Jean Delvare   hwmon: (it87) Fix...
239
240
241
242
243
244
245
246
  	/* The following 3 arrays correspond to the same registers up to
  	 * the IT8720F. The meaning of bits 6-0 depends on the value of bit
  	 * 7, and we want to preserve settings on mode changes, so we have
  	 * to track all values separately.
  	 * Starting with the IT8721F, the manual PWM duty cycles are stored
  	 * in separate registers (8-bit values), so the separate tracking
  	 * is no longer needed, but it is still done to keep the driver
  	 * simple. */
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
247
  	u8 pwm_ctrl[3];		/* Register value */
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
248
  	u8 pwm_duty[3];		/* Manual PWM value set by user */
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
249
  	u8 pwm_temp_map[3];	/* PWM to temp. chan. mapping (bits 1-0) */
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
250
251
252
253
  
  	/* Automatic fan speed control registers */
  	u8 auto_pwm[3][4];	/* [nr][3] is hard-coded */
  	s8 auto_temp[3][5];	/* [nr][0] is point1_temp_hyst */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  };
0df6454da   Jean Delvare   hwmon: (it87) Mov...
255

44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  static u8 in_to_reg(const struct it87_data *data, int nr, long val)
  {
  	long lsb;
  
  	if (data->type == it8721) {
  		if (data->in_scaled & (1 << nr))
  			lsb = 24;
  		else
  			lsb = 12;
  	} else
  		lsb = 16;
  
  	val = DIV_ROUND_CLOSEST(val, lsb);
  	return SENSORS_LIMIT(val, 0, 255);
  }
  
  static int in_from_reg(const struct it87_data *data, int nr, int val)
  {
  	if (data->type == it8721) {
  		if (data->in_scaled & (1 << nr))
  			return val * 24;
  		else
  			return val * 12;
  	} else
  		return val * 16;
  }
0df6454da   Jean Delvare   hwmon: (it87) Mov...
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
  
  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);
  }
  
  static inline u16 FAN16_TO_REG(long rpm)
  {
  	if (rpm == 0)
  		return 0xffff;
  	return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
  }
  
  #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \
  				1350000 / ((val) * (div)))
  /* The divider is fixed to 2 in 16-bit mode */
  #define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
  			     1350000 / ((val) * 2))
  
  #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (((val) - 500) / 1000) : \
  					((val) + 500) / 1000), -128, 127))
  #define TEMP_FROM_REG(val) ((val) * 1000)
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  static u8 pwm_to_reg(const struct it87_data *data, long val)
  {
  	if (data->type == it8721)
  		return val;
  	else
  		return val >> 1;
  }
  
  static int pwm_from_reg(const struct it87_data *data, u8 reg)
  {
  	if (data->type == it8721)
  		return reg;
  	else
  		return (reg & 0x7f) << 1;
  }
0df6454da   Jean Delvare   hwmon: (it87) Mov...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  
  static int DIV_TO_REG(int val)
  {
  	int answer = 0;
  	while (answer < 7 && (val >>= 1))
  		answer++;
  	return answer;
  }
  #define DIV_FROM_REG(val) (1 << (val))
  
  static const unsigned int pwm_freq[8] = {
  	48000000 / 128,
  	24000000 / 128,
  	12000000 / 128,
  	8000000 / 128,
  	6000000 / 128,
  	3000000 / 128,
  	1500000 / 128,
  	750000 / 128,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343

0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
344
345
  static inline int has_16bit_fans(const struct it87_data *data)
  {
816d8c6a2   Andrew Paprocki   hwmon: (it87) Sup...
346
  	/* IT8705F Datasheet 0.4.1, 3h == Version G.
859b9ef30   Andrew Paprocki   hwmon: (it87) Fix...
347
  	   IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
816d8c6a2   Andrew Paprocki   hwmon: (it87) Sup...
348
349
  	   These are the first revisions with 16bit tachometer support. */
  	return (data->type == it87 && data->revision >= 0x03)
859b9ef30   Andrew Paprocki   hwmon: (it87) Fix...
350
  	    || (data->type == it8712 && data->revision >= 0x08)
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
351
  	    || data->type == it8716
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
352
  	    || data->type == it8718
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
353
354
  	    || data->type == it8720
  	    || data->type == it8721;
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
355
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356

4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
357
358
359
360
361
362
363
364
  static inline int has_old_autopwm(const struct it87_data *data)
  {
  	/* The old automatic fan speed control interface is implemented
  	   by IT8705F chips up to revision F and IT8712F chips up to
  	   revision G. */
  	return (data->type == it87 && data->revision < 0x03)
  	    || (data->type == it8712 && data->revision < 0x08);
  }
b74f3fdd9   corentin.labbe   hwmon: convert it...
365
  static int it87_probe(struct platform_device *pdev);
d05461289   Jean Delvare   hwmon: Add missin...
366
  static int __devexit it87_remove(struct platform_device *pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

b74f3fdd9   corentin.labbe   hwmon: convert it...
368
369
  static int it87_read_value(struct it87_data *data, u8 reg);
  static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  static struct it87_data *it87_update_device(struct device *dev);
b74f3fdd9   corentin.labbe   hwmon: convert it...
371
372
  static int it87_check_pwm(struct device *dev);
  static void it87_init_device(struct platform_device *pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373

b74f3fdd9   corentin.labbe   hwmon: convert it...
374
  static struct platform_driver it87_driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
375
  	.driver = {
872188420   Jean Delvare   i2c-isa: Restore ...
376
  		.owner	= THIS_MODULE,
b74f3fdd9   corentin.labbe   hwmon: convert it...
377
  		.name	= DRVNAME,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
378
  	},
b74f3fdd9   corentin.labbe   hwmon: convert it...
379
380
  	.probe	= it87_probe,
  	.remove	= __devexit_p(it87_remove),
fde095090   Jean Delvare   [PATCH] I2C: Sepa...
381
  };
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
382
383
  static ssize_t show_in(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
385
386
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  	struct it87_data *data = it87_update_device(dev);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
388
389
  	return sprintf(buf, "%d
  ", in_from_reg(data, nr, data->in[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
391
392
  static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
394
395
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  	struct it87_data *data = it87_update_device(dev);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
397
398
  	return sprintf(buf, "%d
  ", in_from_reg(data, nr, data->in_min[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
400
401
  static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
403
404
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  	struct it87_data *data = it87_update_device(dev);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
406
407
  	return sprintf(buf, "%d
  ", in_from_reg(data, nr, data->in_max[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
409
410
  static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
412
413
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
414
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
415
  	unsigned long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
416
  	if (kstrtoul(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
417
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
419
  	mutex_lock(&data->update_lock);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
420
  	data->in_min[nr] = in_to_reg(data, nr, val);
b74f3fdd9   corentin.labbe   hwmon: convert it...
421
  	it87_write_value(data, IT87_REG_VIN_MIN(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  			data->in_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
423
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
  	return count;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
426
427
  static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
429
430
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
431
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
432
  	unsigned long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
433
  	if (kstrtoul(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
434
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
436
  	mutex_lock(&data->update_lock);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
437
  	data->in_max[nr] = in_to_reg(data, nr, val);
b74f3fdd9   corentin.labbe   hwmon: convert it...
438
  	it87_write_value(data, IT87_REG_VIN_MAX(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
  			data->in_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
440
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
  	return count;
  }
  
  #define show_in_offset(offset)					\
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
445
446
  static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
  		show_in, NULL, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  
  #define limit_in_offset(offset)					\
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
449
450
451
452
  static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_in_min, set_in_min, offset);		\
  static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_in_max, set_in_max, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  
  show_in_offset(0);
  limit_in_offset(0);
  show_in_offset(1);
  limit_in_offset(1);
  show_in_offset(2);
  limit_in_offset(2);
  show_in_offset(3);
  limit_in_offset(3);
  show_in_offset(4);
  limit_in_offset(4);
  show_in_offset(5);
  limit_in_offset(5);
  show_in_offset(6);
  limit_in_offset(6);
  show_in_offset(7);
  limit_in_offset(7);
  show_in_offset(8);
  
  /* 3 temperatures */
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
473
474
  static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
476
477
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp[nr]));
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
482
483
  static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
485
486
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_high[nr]));
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
491
492
  static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
494
495
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_low[nr]));
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
500
501
  static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
503
504
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
505
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
506
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
507
  	if (kstrtol(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
508
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
510
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	data->temp_high[nr] = TEMP_TO_REG(val);
b74f3fdd9   corentin.labbe   hwmon: convert it...
512
  	it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
513
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  	return count;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
516
517
  static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
519
520
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
521
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
522
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
523
  	if (kstrtol(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
524
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
526
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  	data->temp_low[nr] = TEMP_TO_REG(val);
b74f3fdd9   corentin.labbe   hwmon: convert it...
528
  	it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
529
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
  	return count;
  }
  #define show_temp_offset(offset)					\
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
533
534
535
536
537
538
  static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
  		show_temp, NULL, offset - 1);				\
  static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_temp_max, set_temp_max, offset - 1);		\
  static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_temp_min, set_temp_min, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
542
  
  show_temp_offset(1);
  show_temp_offset(2);
  show_temp_offset(3);
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
543
544
  static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
546
547
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
  	struct it87_data *data = it87_update_device(dev);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
549
550
  	u8 reg = data->sensor;		/* In case the value is updated while
  					   we use it */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
  	if (reg & (1 << nr))
  		return sprintf(buf, "3
  ");  /* thermal diode */
  	if (reg & (8 << nr))
4ed107795   Jean Delvare   hwmon: (it87) Fix...
555
556
  		return sprintf(buf, "4
  ");  /* thermistor */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
  	return sprintf(buf, "0
  ");      /* disabled */
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
560
561
  static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
563
564
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
565
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
566
  	long val;
8acf07c5a   Jean Delvare   hwmon: (it87) Pro...
567
  	u8 reg;
f5f64501e   Jean Delvare   hwmon: (it87) Use...
568

179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
569
  	if (kstrtol(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
570
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571

8acf07c5a   Jean Delvare   hwmon: (it87) Pro...
572
573
574
  	reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
  	reg &= ~(1 << nr);
  	reg &= ~(8 << nr);
4ed107795   Jean Delvare   hwmon: (it87) Fix...
575
576
577
578
579
580
581
  	if (val == 2) {	/* backwards compatibility */
  		dev_warn(dev, "Sensor type 2 is deprecated, please use 4 "
  			 "instead
  ");
  		val = 4;
  	}
  	/* 3 = thermal diode; 4 = thermistor; 0 = disabled */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  	if (val == 3)
8acf07c5a   Jean Delvare   hwmon: (it87) Pro...
583
  		reg |= 1 << nr;
4ed107795   Jean Delvare   hwmon: (it87) Fix...
584
  	else if (val == 4)
8acf07c5a   Jean Delvare   hwmon: (it87) Pro...
585
586
  		reg |= 8 << nr;
  	else if (val != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
  		return -EINVAL;
8acf07c5a   Jean Delvare   hwmon: (it87) Pro...
588
589
590
  
  	mutex_lock(&data->update_lock);
  	data->sensor = reg;
b74f3fdd9   corentin.labbe   hwmon: convert it...
591
  	it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor);
2b3d1d87e   Jean Delvare   hwmon: (it87) Inv...
592
  	data->valid = 0;	/* Force cache refresh */
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
593
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
  	return count;
  }
  #define show_sensor_offset(offset)					\
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
597
598
  static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,	\
  		show_sensor, set_sensor, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
602
603
604
  
  show_sensor_offset(1);
  show_sensor_offset(2);
  show_sensor_offset(3);
  
  /* 3 Fans */
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
605
606
607
608
609
610
611
612
613
614
615
616
  
  static int pwm_mode(const struct it87_data *data, int nr)
  {
  	int ctrl = data->fan_main_ctrl & (1 << nr);
  
  	if (ctrl == 0)					/* Full speed */
  		return 0;
  	if (data->pwm_ctrl[nr] & 0x80)			/* Automatic mode */
  		return 2;
  	else						/* Manual mode */
  		return 1;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
617
618
  static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
620
621
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  	struct it87_data *data = it87_update_device(dev);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
623
624
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan[nr],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
  				DIV_FROM_REG(data->fan_div[nr])));
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
627
628
  static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
630
631
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  	struct it87_data *data = it87_update_device(dev);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
633
634
635
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan_min[nr],
  				DIV_FROM_REG(data->fan_div[nr])));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
637
638
  static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
640
641
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", DIV_FROM_REG(data->fan_div[nr]));
  }
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
646
647
  static ssize_t show_pwm_enable(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
649
650
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
  	struct it87_data *data = it87_update_device(dev);
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
652
653
  	return sprintf(buf, "%d
  ", pwm_mode(data, nr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
655
656
  static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
658
659
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
  	struct it87_data *data = it87_update_device(dev);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
661
662
663
  	return sprintf(buf, "%d
  ",
  		       pwm_from_reg(data, data->pwm_duty[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
  }
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
665
666
667
668
669
670
671
672
673
  static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct it87_data *data = it87_update_device(dev);
  	int index = (data->fan_ctl >> 4) & 0x07;
  
  	return sprintf(buf, "%u
  ", pwm_freq[index]);
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
674
675
  static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
677
678
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
679
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
680
  	long val;
7f999aa72   Jean Delvare   hwmon: Simplify t...
681
  	u8 reg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682

179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
683
  	if (kstrtol(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
684
  		return -EINVAL;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
685
  	mutex_lock(&data->update_lock);
b74f3fdd9   corentin.labbe   hwmon: convert it...
686
  	reg = it87_read_value(data, IT87_REG_FAN_DIV);
07eab46db   Jean Delvare   [PATCH] hwmon: Fi...
687
  	switch (nr) {
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
688
689
690
691
692
693
694
695
696
  	case 0:
  		data->fan_div[nr] = reg & 0x07;
  		break;
  	case 1:
  		data->fan_div[nr] = (reg >> 3) & 0x07;
  		break;
  	case 2:
  		data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
  		break;
07eab46db   Jean Delvare   [PATCH] hwmon: Fi...
697
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
699
  	it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
700
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
  	return count;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
703
704
  static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
706
707
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
708
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
709
  	unsigned long val;
8ab4ec3ef   Jean Delvare   it87: Cleanup set...
710
  	int min;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  	u8 old;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
712
  	if (kstrtoul(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
713
  		return -EINVAL;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
714
  	mutex_lock(&data->update_lock);
b74f3fdd9   corentin.labbe   hwmon: convert it...
715
  	old = it87_read_value(data, IT87_REG_FAN_DIV);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716

8ab4ec3ef   Jean Delvare   it87: Cleanup set...
717
718
  	/* Save fan min limit */
  	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
  
  	switch (nr) {
  	case 0:
  	case 1:
  		data->fan_div[nr] = DIV_TO_REG(val);
  		break;
  	case 2:
  		if (val < 8)
  			data->fan_div[nr] = 1;
  		else
  			data->fan_div[nr] = 3;
  	}
  	val = old & 0x80;
  	val |= (data->fan_div[0] & 0x07);
  	val |= (data->fan_div[1] & 0x07) << 3;
  	if (data->fan_div[2] == 3)
  		val |= 0x1 << 6;
b74f3fdd9   corentin.labbe   hwmon: convert it...
736
  	it87_write_value(data, IT87_REG_FAN_DIV, val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737

8ab4ec3ef   Jean Delvare   it87: Cleanup set...
738
739
  	/* Restore fan min limit */
  	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
740
  	it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]);
8ab4ec3ef   Jean Delvare   it87: Cleanup set...
741

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
742
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  	return count;
  }
cccfc9c4b   Jean Delvare   hwmon: (it87) Val...
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
  
  /* Returns 0 if OK, -EINVAL otherwise */
  static int check_trip_points(struct device *dev, int nr)
  {
  	const struct it87_data *data = dev_get_drvdata(dev);
  	int i, err = 0;
  
  	if (has_old_autopwm(data)) {
  		for (i = 0; i < 3; i++) {
  			if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
  				err = -EINVAL;
  		}
  		for (i = 0; i < 2; i++) {
  			if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
  				err = -EINVAL;
  		}
  	}
  
  	if (err) {
  		dev_err(dev, "Inconsistent trip points, not switching to "
  			"automatic mode
  ");
  		dev_err(dev, "Adjust the trip points and try again
  ");
  	}
  	return err;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
772
773
  static ssize_t set_pwm_enable(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
775
776
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
777
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
778
  	long val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779

179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
780
  	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2)
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
781
  		return -EINVAL;
cccfc9c4b   Jean Delvare   hwmon: (it87) Val...
782
783
784
785
786
  	/* Check trip points before switching to automatic mode */
  	if (val == 2) {
  		if (check_trip_points(dev, nr) < 0)
  			return -EINVAL;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
787
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
  
  	if (val == 0) {
  		int tmp;
  		/* make sure the fan is on when in on/off mode */
b74f3fdd9   corentin.labbe   hwmon: convert it...
792
793
  		tmp = it87_read_value(data, IT87_REG_FAN_CTL);
  		it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
  		/* set on/off mode */
  		data->fan_main_ctrl &= ~(1 << nr);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
796
797
  		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
  				 data->fan_main_ctrl);
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
798
799
  	} else {
  		if (val == 1)				/* Manual mode */
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
800
801
802
  			data->pwm_ctrl[nr] = data->type == it8721 ?
  					     data->pwm_temp_map[nr] :
  					     data->pwm_duty[nr];
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
803
804
805
  		else					/* Automatic mode */
  			data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
  		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
  		/* set SmartGuardian mode */
  		data->fan_main_ctrl |= (1 << nr);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
808
809
  		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
  				 data->fan_main_ctrl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
811
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
  	return count;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
814
815
  static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  {
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
817
818
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
819
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
820
  	long val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821

179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
822
  	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  		return -EINVAL;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
824
  	mutex_lock(&data->update_lock);
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  	if (data->type == it8721) {
  		/* If we are in automatic mode, the PWM duty cycle register
  		 * is read-only so we can't write the value */
  		if (data->pwm_ctrl[nr] & 0x80) {
  			mutex_unlock(&data->update_lock);
  			return -EBUSY;
  		}
  		data->pwm_duty[nr] = pwm_to_reg(data, val);
  		it87_write_value(data, IT87_REG_PWM_DUTY(nr),
  				 data->pwm_duty[nr]);
  	} else {
  		data->pwm_duty[nr] = pwm_to_reg(data, val);
  		/* If we are in manual mode, write the duty cycle immediately;
  		 * otherwise, just store it for later use. */
  		if (!(data->pwm_ctrl[nr] & 0x80)) {
  			data->pwm_ctrl[nr] = data->pwm_duty[nr];
  			it87_write_value(data, IT87_REG_PWM(nr),
  					 data->pwm_ctrl[nr]);
  		}
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
844
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
845
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
847
  	return count;
  }
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
848
849
850
  static ssize_t set_pwm_freq(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
851
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
852
  	unsigned long val;
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
853
  	int i;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
854
  	if (kstrtoul(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
855
  		return -EINVAL;
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
856
857
858
859
860
861
862
  	/* Search for the nearest available frequency */
  	for (i = 0; i < 7; i++) {
  		if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
  			break;
  	}
  
  	mutex_lock(&data->update_lock);
b74f3fdd9   corentin.labbe   hwmon: convert it...
863
  	data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f;
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
864
  	data->fan_ctl |= i << 4;
b74f3fdd9   corentin.labbe   hwmon: convert it...
865
  	it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl);
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
866
867
868
869
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
  static ssize_t show_pwm_temp_map(struct device *dev,
  		struct device_attribute *attr, char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  
  	struct it87_data *data = it87_update_device(dev);
  	int map;
  
  	if (data->pwm_temp_map[nr] < 3)
  		map = 1 << data->pwm_temp_map[nr];
  	else
  		map = 0;			/* Should never happen */
  	return sprintf(buf, "%d
  ", map);
  }
  static ssize_t set_pwm_temp_map(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  
  	struct it87_data *data = dev_get_drvdata(dev);
  	long val;
  	u8 reg;
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
895
896
897
898
899
900
901
  	/* This check can go away if we ever support automatic fan speed
  	   control on newer chips. */
  	if (!has_old_autopwm(data)) {
  		dev_notice(dev, "Mapping change disabled for safety reasons
  ");
  		return -EINVAL;
  	}
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
902
  	if (kstrtol(buf, 10, &val) < 0)
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  		return -EINVAL;
  
  	switch (val) {
  	case (1 << 0):
  		reg = 0x00;
  		break;
  	case (1 << 1):
  		reg = 0x01;
  		break;
  	case (1 << 2):
  		reg = 0x02;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	mutex_lock(&data->update_lock);
  	data->pwm_temp_map[nr] = reg;
  	/* If we are in automatic mode, write the temp mapping immediately;
  	 * otherwise, just store it for later use. */
  	if (data->pwm_ctrl[nr] & 0x80) {
  		data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
  		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
  	}
  	mutex_unlock(&data->update_lock);
  	return count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930

4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
931
932
933
934
935
936
937
938
  static ssize_t show_auto_pwm(struct device *dev,
  		struct device_attribute *attr, char *buf)
  {
  	struct it87_data *data = it87_update_device(dev);
  	struct sensor_device_attribute_2 *sensor_attr =
  			to_sensor_dev_attr_2(attr);
  	int nr = sensor_attr->nr;
  	int point = sensor_attr->index;
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
939
940
941
  	return sprintf(buf, "%d
  ",
  		       pwm_from_reg(data, data->auto_pwm[nr][point]));
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
942
943
944
945
946
947
948
949
950
951
952
  }
  
  static ssize_t set_auto_pwm(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
  {
  	struct it87_data *data = dev_get_drvdata(dev);
  	struct sensor_device_attribute_2 *sensor_attr =
  			to_sensor_dev_attr_2(attr);
  	int nr = sensor_attr->nr;
  	int point = sensor_attr->index;
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
953
  	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
954
955
956
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
957
  	data->auto_pwm[nr][point] = pwm_to_reg(data, val);
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
  	it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
  			 data->auto_pwm[nr][point]);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  static ssize_t show_auto_temp(struct device *dev,
  		struct device_attribute *attr, char *buf)
  {
  	struct it87_data *data = it87_update_device(dev);
  	struct sensor_device_attribute_2 *sensor_attr =
  			to_sensor_dev_attr_2(attr);
  	int nr = sensor_attr->nr;
  	int point = sensor_attr->index;
  
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->auto_temp[nr][point]));
  }
  
  static ssize_t set_auto_temp(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
  {
  	struct it87_data *data = dev_get_drvdata(dev);
  	struct sensor_device_attribute_2 *sensor_attr =
  			to_sensor_dev_attr_2(attr);
  	int nr = sensor_attr->nr;
  	int point = sensor_attr->index;
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
986
  	if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
987
988
989
990
991
992
993
994
995
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
  	data->auto_temp[nr][point] = TEMP_TO_REG(val);
  	it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
  			 data->auto_temp[nr][point]);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
996
997
998
999
1000
1001
1002
  #define show_fan_offset(offset)					\
  static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
  		show_fan, NULL, offset - 1);			\
  static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
  		show_fan_min, set_fan_min, offset - 1);		\
  static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
  		show_fan_div, set_fan_div, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
1005
1006
1007
1008
  
  show_fan_offset(1);
  show_fan_offset(2);
  show_fan_offset(3);
  
  #define show_pwm_offset(offset)						\
20ad93d4e   Jean Delvare   [PATCH] I2C: driv...
1009
1010
1011
  static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,	\
  		show_pwm_enable, set_pwm_enable, offset - 1);		\
  static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,		\
f8d0c19a9   Jean Delvare   hwmon/it87: Add P...
1012
1013
1014
  		show_pwm, set_pwm, offset - 1);				\
  static DEVICE_ATTR(pwm##offset##_freq,					\
  		(offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO),		\
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
1015
1016
  		show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));	\
  static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp,		\
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  		S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map,	\
  		offset - 1);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm,		\
  		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
  		offset - 1, 0);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm,		\
  		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
  		offset - 1, 1);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm,		\
  		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
  		offset - 1, 2);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm,		\
  		S_IRUGO, show_auto_pwm, NULL, offset - 1, 3);		\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp,		\
  		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
  		offset - 1, 1);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst,	\
  		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
  		offset - 1, 0);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp,		\
  		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
  		offset - 1, 2);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp,		\
  		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
  		offset - 1, 3);						\
  static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp,		\
  		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
  		offset - 1, 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
1048
  
  show_pwm_offset(1);
  show_pwm_offset(2);
  show_pwm_offset(3);
17d648bf5   Jean Delvare   it87: Add support...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
  /* A different set of callbacks for 16-bit fans */
  static ssize_t show_fan16(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN16_FROM_REG(data->fan[nr]));
  }
  
  static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN16_FROM_REG(data->fan_min[nr]));
  }
  
  static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1075
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
1076
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
1077
  	if (kstrtol(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
1078
  		return -EINVAL;
17d648bf5   Jean Delvare   it87: Add support...
1079
1080
1081
  
  	mutex_lock(&data->update_lock);
  	data->fan_min[nr] = FAN16_TO_REG(val);
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
1082
  	it87_write_value(data, IT87_REG_FAN_MIN[nr],
17d648bf5   Jean Delvare   it87: Add support...
1083
  			 data->fan_min[nr] & 0xff);
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
1084
  	it87_write_value(data, IT87_REG_FANX_MIN[nr],
17d648bf5   Jean Delvare   it87: Add support...
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
  			 data->fan_min[nr] >> 8);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  /* We want to use the same sysfs file names as 8-bit fans, but we need
     different variable names, so we have to use SENSOR_ATTR instead of
     SENSOR_DEVICE_ATTR. */
  #define show_fan16_offset(offset) \
  static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \
  	= SENSOR_ATTR(fan##offset##_input, S_IRUGO,		\
  		show_fan16, NULL, offset - 1);			\
  static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \
  	= SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_fan16_min, set_fan16_min, offset - 1)
  
  show_fan16_offset(1);
  show_fan16_offset(2);
  show_fan16_offset(3);
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
1104
1105
  show_fan16_offset(4);
  show_fan16_offset(5);
17d648bf5   Jean Delvare   it87: Add support...
1106

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
  /* Alarms */
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1108
1109
  static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
1111
  {
  	struct it87_data *data = it87_update_device(dev);
68188ba7d   Jean Delvare   [PATCH] I2C: Kill...
1112
1113
  	return sprintf(buf, "%u
  ", data->alarms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
  }
1d66c64c3   Jean Delvare   [PATCH] I2C: Fix ...
1115
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116

0124dd78e   Jean Delvare   hwmon: (it87) Add...
1117
1118
1119
1120
1121
1122
1123
1124
  static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%u
  ", (data->alarms >> bitnr) & 1);
  }
3d30f9e69   Jean Delvare   hwmon: (it87) Add...
1125
1126
1127
1128
1129
1130
1131
  
  static ssize_t clear_intrusion(struct device *dev, struct device_attribute
  		*attr, const char *buf, size_t count)
  {
  	struct it87_data *data = dev_get_drvdata(dev);
  	long val;
  	int config;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
1132
  	if (kstrtol(buf, 10, &val) < 0 || val != 0)
3d30f9e69   Jean Delvare   hwmon: (it87) Add...
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
  	config = it87_read_value(data, IT87_REG_CONFIG);
  	if (config < 0) {
  		count = config;
  	} else {
  		config |= 1 << 5;
  		it87_write_value(data, IT87_REG_CONFIG, config);
  		/* Invalidate cache to force re-read */
  		data->valid = 0;
  	}
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
  static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
  static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
  static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
  static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
  static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
  static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
  static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
  static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2);
  static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
  static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
  static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
  static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
3d30f9e69   Jean Delvare   hwmon: (it87) Add...
1165
1166
  static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
  			  show_alarm, clear_intrusion, 4);
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1167

d9b327c31   Jean Delvare   hwmon: (it87) Add...
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct it87_data *data = it87_update_device(dev);
  	return sprintf(buf, "%u
  ", (data->beeps >> bitnr) & 1);
  }
  static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct it87_data *data = dev_get_drvdata(dev);
  	long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
1182
  	if (kstrtol(buf, 10, &val) < 0
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  	 || (val != 0 && val != 1))
  		return -EINVAL;
  
  	mutex_lock(&data->update_lock);
  	data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
  	if (val)
  		data->beeps |= (1 << bitnr);
  	else
  		data->beeps &= ~(1 << bitnr);
  	it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps);
  	mutex_unlock(&data->update_lock);
  	return count;
  }
  
  static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
  			  show_beep, set_beep, 1);
  static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1);
  static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1);
  /* fanX_beep writability is set later */
  static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0);
  static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0);
  static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0);
  static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0);
  static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0);
  static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
  			  show_beep, set_beep, 2);
  static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2);
  static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1216
1217
  static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  {
90d6619a9   Jean Delvare   hwmon: VRM is not...
1219
  	struct it87_data *data = dev_get_drvdata(dev);
a7be58a12   Jean Delvare   [PATCH] hwmon: it...
1220
1221
  	return sprintf(buf, "%u
  ", data->vrm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
  }
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1223
1224
  static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1226
  	struct it87_data *data = dev_get_drvdata(dev);
f5f64501e   Jean Delvare   hwmon: (it87) Use...
1227
  	unsigned long val;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
1228
  	if (kstrtoul(buf, 10, &val) < 0)
f5f64501e   Jean Delvare   hwmon: (it87) Use...
1229
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231
1232
1233
1234
1235
  	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
1236

5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1237
1238
  static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
1240
1241
1242
1243
1244
  {
  	struct it87_data *data = it87_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);
87808be4f   Jean Delvare   Fix unchecked ret...
1245

738e5e053   Jean Delvare   hwmon: (it87) Exp...
1246
1247
1248
1249
1250
1251
1252
1253
  static ssize_t show_label(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	static const char *labels[] = {
  		"+5V",
  		"5VSB",
  		"Vbat",
  	};
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1254
1255
1256
1257
1258
1259
  	static const char *labels_it8721[] = {
  		"+3.3V",
  		"3VSB",
  		"Vbat",
  	};
  	struct it87_data *data = dev_get_drvdata(dev);
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1260
  	int nr = to_sensor_dev_attr(attr)->index;
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1261
1262
1263
  	return sprintf(buf, "%s
  ", data->type == it8721 ? labels_it8721[nr]
  							 : labels[nr]);
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1264
1265
1266
1267
  }
  static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
  static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
  static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
b74f3fdd9   corentin.labbe   hwmon: convert it...
1268
1269
1270
1271
1272
1273
1274
1275
  static ssize_t show_name(struct device *dev, struct device_attribute
  			 *devattr, char *buf)
  {
  	struct it87_data *data = dev_get_drvdata(dev);
  	return sprintf(buf, "%s
  ", data->name);
  }
  static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
87808be4f   Jean Delvare   Fix unchecked ret...
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
  static struct attribute *it87_attributes[] = {
  	&sensor_dev_attr_in0_input.dev_attr.attr,
  	&sensor_dev_attr_in1_input.dev_attr.attr,
  	&sensor_dev_attr_in2_input.dev_attr.attr,
  	&sensor_dev_attr_in3_input.dev_attr.attr,
  	&sensor_dev_attr_in4_input.dev_attr.attr,
  	&sensor_dev_attr_in5_input.dev_attr.attr,
  	&sensor_dev_attr_in6_input.dev_attr.attr,
  	&sensor_dev_attr_in7_input.dev_attr.attr,
  	&sensor_dev_attr_in8_input.dev_attr.attr,
  	&sensor_dev_attr_in0_min.dev_attr.attr,
  	&sensor_dev_attr_in1_min.dev_attr.attr,
  	&sensor_dev_attr_in2_min.dev_attr.attr,
  	&sensor_dev_attr_in3_min.dev_attr.attr,
  	&sensor_dev_attr_in4_min.dev_attr.attr,
  	&sensor_dev_attr_in5_min.dev_attr.attr,
  	&sensor_dev_attr_in6_min.dev_attr.attr,
  	&sensor_dev_attr_in7_min.dev_attr.attr,
  	&sensor_dev_attr_in0_max.dev_attr.attr,
  	&sensor_dev_attr_in1_max.dev_attr.attr,
  	&sensor_dev_attr_in2_max.dev_attr.attr,
  	&sensor_dev_attr_in3_max.dev_attr.attr,
  	&sensor_dev_attr_in4_max.dev_attr.attr,
  	&sensor_dev_attr_in5_max.dev_attr.attr,
  	&sensor_dev_attr_in6_max.dev_attr.attr,
  	&sensor_dev_attr_in7_max.dev_attr.attr,
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1302
1303
1304
1305
1306
1307
1308
1309
  	&sensor_dev_attr_in0_alarm.dev_attr.attr,
  	&sensor_dev_attr_in1_alarm.dev_attr.attr,
  	&sensor_dev_attr_in2_alarm.dev_attr.attr,
  	&sensor_dev_attr_in3_alarm.dev_attr.attr,
  	&sensor_dev_attr_in4_alarm.dev_attr.attr,
  	&sensor_dev_attr_in5_alarm.dev_attr.attr,
  	&sensor_dev_attr_in6_alarm.dev_attr.attr,
  	&sensor_dev_attr_in7_alarm.dev_attr.attr,
87808be4f   Jean Delvare   Fix unchecked ret...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
  
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_temp1_min.dev_attr.attr,
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
  	&sensor_dev_attr_temp3_min.dev_attr.attr,
  	&sensor_dev_attr_temp1_type.dev_attr.attr,
  	&sensor_dev_attr_temp2_type.dev_attr.attr,
  	&sensor_dev_attr_temp3_type.dev_attr.attr,
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1323
1324
1325
  	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
87808be4f   Jean Delvare   Fix unchecked ret...
1326
1327
  
  	&dev_attr_alarms.attr,
3d30f9e69   Jean Delvare   hwmon: (it87) Add...
1328
  	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
b74f3fdd9   corentin.labbe   hwmon: convert it...
1329
  	&dev_attr_name.attr,
87808be4f   Jean Delvare   Fix unchecked ret...
1330
1331
1332
1333
1334
1335
  	NULL
  };
  
  static const struct attribute_group it87_group = {
  	.attrs = it87_attributes,
  };
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
  static struct attribute *it87_attributes_beep[] = {
  	&sensor_dev_attr_in0_beep.dev_attr.attr,
  	&sensor_dev_attr_in1_beep.dev_attr.attr,
  	&sensor_dev_attr_in2_beep.dev_attr.attr,
  	&sensor_dev_attr_in3_beep.dev_attr.attr,
  	&sensor_dev_attr_in4_beep.dev_attr.attr,
  	&sensor_dev_attr_in5_beep.dev_attr.attr,
  	&sensor_dev_attr_in6_beep.dev_attr.attr,
  	&sensor_dev_attr_in7_beep.dev_attr.attr,
  
  	&sensor_dev_attr_temp1_beep.dev_attr.attr,
  	&sensor_dev_attr_temp2_beep.dev_attr.attr,
  	&sensor_dev_attr_temp3_beep.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group it87_group_beep = {
  	.attrs = it87_attributes_beep,
  };
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1355
  static struct attribute *it87_attributes_fan16[5][3+1] = { {
87808be4f   Jean Delvare   Fix unchecked ret...
1356
1357
  	&sensor_dev_attr_fan1_input16.dev_attr.attr,
  	&sensor_dev_attr_fan1_min16.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1358
1359
1360
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
  	NULL
  }, {
87808be4f   Jean Delvare   Fix unchecked ret...
1361
1362
  	&sensor_dev_attr_fan2_input16.dev_attr.attr,
  	&sensor_dev_attr_fan2_min16.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1363
1364
1365
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
  	NULL
  }, {
87808be4f   Jean Delvare   Fix unchecked ret...
1366
1367
  	&sensor_dev_attr_fan3_input16.dev_attr.attr,
  	&sensor_dev_attr_fan3_min16.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1368
1369
1370
  	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
  	NULL
  }, {
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
1371
1372
  	&sensor_dev_attr_fan4_input16.dev_attr.attr,
  	&sensor_dev_attr_fan4_min16.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1373
1374
1375
  	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
  	NULL
  }, {
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
1376
1377
  	&sensor_dev_attr_fan5_input16.dev_attr.attr,
  	&sensor_dev_attr_fan5_min16.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
  	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
  	NULL
  } };
  
  static const struct attribute_group it87_group_fan16[5] = {
  	{ .attrs = it87_attributes_fan16[0] },
  	{ .attrs = it87_attributes_fan16[1] },
  	{ .attrs = it87_attributes_fan16[2] },
  	{ .attrs = it87_attributes_fan16[3] },
  	{ .attrs = it87_attributes_fan16[4] },
  };
87808be4f   Jean Delvare   Fix unchecked ret...
1389

723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1390
  static struct attribute *it87_attributes_fan[3][4+1] = { {
87808be4f   Jean Delvare   Fix unchecked ret...
1391
1392
1393
  	&sensor_dev_attr_fan1_input.dev_attr.attr,
  	&sensor_dev_attr_fan1_min.dev_attr.attr,
  	&sensor_dev_attr_fan1_div.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1394
1395
1396
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
  	NULL
  }, {
87808be4f   Jean Delvare   Fix unchecked ret...
1397
1398
1399
  	&sensor_dev_attr_fan2_input.dev_attr.attr,
  	&sensor_dev_attr_fan2_min.dev_attr.attr,
  	&sensor_dev_attr_fan2_div.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1400
1401
1402
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
  	NULL
  }, {
87808be4f   Jean Delvare   Fix unchecked ret...
1403
1404
1405
  	&sensor_dev_attr_fan3_input.dev_attr.attr,
  	&sensor_dev_attr_fan3_min.dev_attr.attr,
  	&sensor_dev_attr_fan3_div.dev_attr.attr,
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1406
  	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  	NULL
  } };
  
  static const struct attribute_group it87_group_fan[3] = {
  	{ .attrs = it87_attributes_fan[0] },
  	{ .attrs = it87_attributes_fan[1] },
  	{ .attrs = it87_attributes_fan[2] },
  };
  
  static const struct attribute_group *
  it87_get_fan_group(const struct it87_data *data)
  {
  	return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan;
  }
0124dd78e   Jean Delvare   hwmon: (it87) Add...
1421

723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1422
  static struct attribute *it87_attributes_pwm[3][4+1] = { {
87808be4f   Jean Delvare   Fix unchecked ret...
1423
  	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
87808be4f   Jean Delvare   Fix unchecked ret...
1424
  	&sensor_dev_attr_pwm1.dev_attr.attr,
d5b0b5d62   Jean Delvare   hwmon: (it87) Del...
1425
  	&dev_attr_pwm1_freq.attr,
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
1426
  	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1427
1428
1429
1430
1431
  	NULL
  }, {
  	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
  	&sensor_dev_attr_pwm2.dev_attr.attr,
  	&dev_attr_pwm2_freq.attr,
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
1432
  	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1433
1434
1435
1436
1437
  	NULL
  }, {
  	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
  	&sensor_dev_attr_pwm3.dev_attr.attr,
  	&dev_attr_pwm3_freq.attr,
94ac7ee61   Jean Delvare   hwmon: (it87) Exp...
1438
  	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1439
1440
  	NULL
  } };
87808be4f   Jean Delvare   Fix unchecked ret...
1441

723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1442
1443
1444
1445
1446
  static const struct attribute_group it87_group_pwm[3] = {
  	{ .attrs = it87_attributes_pwm[0] },
  	{ .attrs = it87_attributes_pwm[1] },
  	{ .attrs = it87_attributes_pwm[2] },
  };
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  static struct attribute *it87_attributes_autopwm[3][9+1] = { {
  	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
  	NULL
  }, {
  	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
  	NULL
  }, {
  	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
  	&sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
  	NULL
  } };
  
  static const struct attribute_group it87_group_autopwm[3] = {
  	{ .attrs = it87_attributes_autopwm[0] },
  	{ .attrs = it87_attributes_autopwm[1] },
  	{ .attrs = it87_attributes_autopwm[2] },
  };
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1487
1488
1489
1490
1491
1492
1493
  static struct attribute *it87_attributes_fan_beep[] = {
  	&sensor_dev_attr_fan1_beep.dev_attr.attr,
  	&sensor_dev_attr_fan2_beep.dev_attr.attr,
  	&sensor_dev_attr_fan3_beep.dev_attr.attr,
  	&sensor_dev_attr_fan4_beep.dev_attr.attr,
  	&sensor_dev_attr_fan5_beep.dev_attr.attr,
  };
6a8d7acfb   Jean Delvare   hwmon: (it87) Cre...
1494
  static struct attribute *it87_attributes_vid[] = {
87808be4f   Jean Delvare   Fix unchecked ret...
1495
1496
1497
1498
  	&dev_attr_vrm.attr,
  	&dev_attr_cpu0_vid.attr,
  	NULL
  };
6a8d7acfb   Jean Delvare   hwmon: (it87) Cre...
1499
1500
  static const struct attribute_group it87_group_vid = {
  	.attrs = it87_attributes_vid,
87808be4f   Jean Delvare   Fix unchecked ret...
1501
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502

738e5e053   Jean Delvare   hwmon: (it87) Exp...
1503
1504
1505
1506
1507
1508
1509
1510
  static struct attribute *it87_attributes_label[] = {
  	&sensor_dev_attr_in3_label.dev_attr.attr,
  	&sensor_dev_attr_in7_label.dev_attr.attr,
  	&sensor_dev_attr_in8_label.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group it87_group_label = {
fa8b69758   Jean Delvare   hwmon: (it87) Fix...
1511
  	.attrs = it87_attributes_label,
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1512
  };
2d8672c5a   Jean Delvare   [PATCH] I2C: Sepa...
1513
  /* SuperIO detection - will change isa_address if a chip is found */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1514
1515
  static int __init it87_find(unsigned short *address,
  	struct it87_sio_data *sio_data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
  {
5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
1517
  	int err;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1518
  	u16 chip_type;
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
1519
  	const char *board_vendor, *board_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520

5b0380c94   Nat Gurumoorthy   hwmon: (it87) Use...
1521
1522
1523
1524
1525
  	err = superio_enter();
  	if (err)
  		return err;
  
  	err = -ENODEV;
67b671bce   Jean Delvare   hwmon: Let the us...
1526
  	chip_type = force_id ? force_id : superio_inw(DEVID);
b74f3fdd9   corentin.labbe   hwmon: convert it...
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
  
  	switch (chip_type) {
  	case IT8705F_DEVID:
  		sio_data->type = it87;
  		break;
  	case IT8712F_DEVID:
  		sio_data->type = it8712;
  		break;
  	case IT8716F_DEVID:
  	case IT8726F_DEVID:
  		sio_data->type = it8716;
  		break;
  	case IT8718F_DEVID:
  		sio_data->type = it8718;
  		break;
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
1542
1543
1544
  	case IT8720F_DEVID:
  		sio_data->type = it8720;
  		break;
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1545
1546
1547
  	case IT8721F_DEVID:
  		sio_data->type = it8721;
  		break;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1548
1549
1550
  	case 0xffff:	/* No device at all */
  		goto exit;
  	default:
a8ca10379   Joe Perches   hwmon: (it87) Use...
1551
1552
  		pr_debug("Unsupported chip (DEVID=0x%x)
  ", chip_type);
b74f3fdd9   corentin.labbe   hwmon: convert it...
1553
1554
  		goto exit;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555

87673dd73   Jean Delvare   it87: Add support...
1556
  	superio_select(PME);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
  	if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
1558
1559
  		pr_info("Device not activated, skipping
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
1561
1562
1563
1564
  		goto exit;
  	}
  
  	*address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
  	if (*address == 0) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
1565
1566
  		pr_info("Base address not set, skipping
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
1570
  		goto exit;
  	}
  
  	err = 0;
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
1571
  	sio_data->revision = superio_inb(DEVREV) & 0x0f;
a8ca10379   Joe Perches   hwmon: (it87) Use...
1572
1573
  	pr_info("Found IT%04xF chip at 0x%x, revision %d
  ",
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
1574
  		chip_type, *address, sio_data->revision);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575

738e5e053   Jean Delvare   hwmon: (it87) Exp...
1576
1577
  	/* in8 (Vbat) is always internal */
  	sio_data->internal = (1 << 2);
87673dd73   Jean Delvare   it87: Add support...
1578
  	/* Read GPIO config and VID value from LDN 7 (GPIO) */
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1579
1580
1581
  	if (sio_data->type == it87) {
  		/* The IT8705F doesn't have VID pins at all */
  		sio_data->skip_vid = 1;
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1582
1583
1584
1585
  
  		/* The IT8705F has a different LD number for GPIO */
  		superio_select(5);
  		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1586
  	} else {
87673dd73   Jean Delvare   it87: Add support...
1587
1588
1589
  		int reg;
  
  		superio_select(GPIO);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1590

895ff2676   Jean Delvare   hwmon: (it87) Ver...
1591
  		reg = superio_inb(IT87_SIO_GPIO3_REG);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1592
1593
  		if (sio_data->type == it8721) {
  			/* The IT8721F/IT8758E doesn't have VID pins at all */
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1594
  			sio_data->skip_vid = 1;
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1595
1596
1597
  		} else {
  			/* We need at least 4 VID pins */
  			if (reg & 0x0f) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
1598
1599
  				pr_info("VID is disabled (pins used for GPIO)
  ");
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1600
1601
  				sio_data->skip_vid = 1;
  			}
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1602
  		}
591ec6509   Jean Delvare   hwmon: (it87) Che...
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
  		/* Check if fan3 is there or not */
  		if (reg & (1 << 6))
  			sio_data->skip_pwm |= (1 << 2);
  		if (reg & (1 << 7))
  			sio_data->skip_fan |= (1 << 2);
  
  		/* Check if fan2 is there or not */
  		reg = superio_inb(IT87_SIO_GPIO5_REG);
  		if (reg & (1 << 1))
  			sio_data->skip_pwm |= (1 << 1);
  		if (reg & (1 << 2))
  			sio_data->skip_fan |= (1 << 1);
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1615
1616
  		if ((sio_data->type == it8718 || sio_data->type == it8720)
  		 && !(sio_data->skip_vid))
b74f3fdd9   corentin.labbe   hwmon: convert it...
1617
  			sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
87673dd73   Jean Delvare   it87: Add support...
1618
1619
  
  		reg = superio_inb(IT87_SIO_PINX2_REG);
436cad2a4   Jean Delvare   hwmon: (it87) Fix...
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
  		/*
  		 * The IT8720F has no VIN7 pin, so VCCH should always be
  		 * routed internally to VIN7 with an internal divider.
  		 * Curiously, there still is a configuration bit to control
  		 * this, which means it can be set incorrectly. And even
  		 * more curiously, many boards out there are improperly
  		 * configured, even though the IT8720F datasheet claims
  		 * that the internal routing of VCCH to VIN7 is the default
  		 * setting. So we force the internal routing in this case.
  		 */
  		if (sio_data->type == it8720 && !(reg & (1 << 1))) {
  			reg |= (1 << 1);
  			superio_outb(IT87_SIO_PINX2_REG, reg);
a8ca10379   Joe Perches   hwmon: (it87) Use...
1633
1634
  			pr_notice("Routing internal VCCH to in7
  ");
436cad2a4   Jean Delvare   hwmon: (it87) Fix...
1635
  		}
87673dd73   Jean Delvare   it87: Add support...
1636
  		if (reg & (1 << 0))
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1637
  			sio_data->internal |= (1 << 0);
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1638
  		if ((reg & (1 << 1)) || sio_data->type == it8721)
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1639
  			sio_data->internal |= (1 << 1);
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1640
1641
  
  		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
87673dd73   Jean Delvare   it87: Add support...
1642
  	}
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1643
  	if (sio_data->beep_pin)
a8ca10379   Joe Perches   hwmon: (it87) Use...
1644
1645
  		pr_info("Beeping is supported
  ");
87673dd73   Jean Delvare   it87: Add support...
1646

98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
  	/* Disable specific features based on DMI strings */
  	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
  	board_name = dmi_get_system_info(DMI_BOARD_NAME);
  	if (board_vendor && board_name) {
  		if (strcmp(board_vendor, "nVIDIA") == 0
  		 && strcmp(board_name, "FN68PT") == 0) {
  			/* On the Shuttle SN68PT, FAN_CTL2 is apparently not
  			   connected to a fan, but to something else. One user
  			   has reported instant system power-off when changing
  			   the PWM2 duty cycle, so we disable it.
  			   I use the board name string as the trigger in case
  			   the same board is ever used in other systems. */
a8ca10379   Joe Perches   hwmon: (it87) Use...
1659
1660
  			pr_info("Disabling pwm2 due to hardware constraints
  ");
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
1661
1662
1663
  			sio_data->skip_pwm = (1 << 1);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
1666
1667
  exit:
  	superio_exit();
  	return err;
  }
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1668
1669
1670
1671
1672
1673
1674
1675
  static void it87_remove_files(struct device *dev)
  {
  	struct it87_data *data = platform_get_drvdata(pdev);
  	struct it87_sio_data *sio_data = dev->platform_data;
  	const struct attribute_group *fan_group = it87_get_fan_group(data);
  	int i;
  
  	sysfs_remove_group(&dev->kobj, &it87_group);
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1676
1677
  	if (sio_data->beep_pin)
  		sysfs_remove_group(&dev->kobj, &it87_group_beep);
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1678
1679
1680
1681
  	for (i = 0; i < 5; i++) {
  		if (!(data->has_fan & (1 << i)))
  			continue;
  		sysfs_remove_group(&dev->kobj, &fan_group[i]);
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1682
1683
1684
  		if (sio_data->beep_pin)
  			sysfs_remove_file(&dev->kobj,
  					  it87_attributes_fan_beep[i]);
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1685
1686
1687
1688
1689
  	}
  	for (i = 0; i < 3; i++) {
  		if (sio_data->skip_pwm & (1 << 0))
  			continue;
  		sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
1690
1691
1692
  		if (has_old_autopwm(data))
  			sysfs_remove_group(&dev->kobj,
  					   &it87_group_autopwm[i]);
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1693
  	}
6a8d7acfb   Jean Delvare   hwmon: (it87) Cre...
1694
1695
  	if (!sio_data->skip_vid)
  		sysfs_remove_group(&dev->kobj, &it87_group_vid);
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1696
  	sysfs_remove_group(&dev->kobj, &it87_group_label);
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1697
  }
b74f3fdd9   corentin.labbe   hwmon: convert it...
1698
  static int __devinit it87_probe(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1699
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  	struct it87_data *data;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1701
1702
1703
  	struct resource *res;
  	struct device *dev = &pdev->dev;
  	struct it87_sio_data *sio_data = dev->platform_data;
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1704
1705
  	const struct attribute_group *fan_group;
  	int err = 0, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
  	int enable_pwm_interface;
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1707
  	int fan_beep_need_rw;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1708
1709
1710
1711
1712
  	static const char *names[] = {
  		"it87",
  		"it8712",
  		"it8716",
  		"it8718",
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
1713
  		"it8720",
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1714
  		"it8721",
b74f3fdd9   corentin.labbe   hwmon: convert it...
1715
1716
1717
  	};
  
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
1718
  	if (!request_region(res->start, IT87_EC_EXTENT, DRVNAME)) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1719
1720
1721
  		dev_err(dev, "Failed to request region 0x%lx-0x%lx
  ",
  			(unsigned long)res->start,
87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
1722
  			(unsigned long)(res->start + IT87_EC_EXTENT - 1));
8e9afcbbd   Jean Delvare   hwmon/it87: Remov...
1723
1724
1725
  		err = -EBUSY;
  		goto ERROR0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726

5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1727
1728
  	data = kzalloc(sizeof(struct it87_data), GFP_KERNEL);
  	if (!data) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
1730
1731
  		err = -ENOMEM;
  		goto ERROR1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732

b74f3fdd9   corentin.labbe   hwmon: convert it...
1733
1734
  	data->addr = res->start;
  	data->type = sio_data->type;
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
1735
  	data->revision = sio_data->revision;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1736
  	data->name = names[sio_data->type];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1737
1738
  
  	/* Now, we do the remaining detection. */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1739
1740
  	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
  	 || it87_read_value(data, IT87_REG_CHIPID) != 0x90) {
8e9afcbbd   Jean Delvare   hwmon/it87: Remov...
1741
1742
  		err = -ENODEV;
  		goto ERROR2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
  	}
b74f3fdd9   corentin.labbe   hwmon: convert it...
1744
  	platform_set_drvdata(pdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1746
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
  	/* Check PWM configuration */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1749
  	enable_pwm_interface = it87_check_pwm(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750

44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
1751
1752
1753
1754
1755
1756
1757
1758
1759
  	/* Starting with IT8721F, we handle scaling of internal voltages */
  	if (data->type == it8721) {
  		if (sio_data->internal & (1 << 0))
  			data->in_scaled |= (1 << 3);	/* in3 is AVCC */
  		if (sio_data->internal & (1 << 1))
  			data->in_scaled |= (1 << 7);	/* in7 is VSB */
  		if (sio_data->internal & (1 << 2))
  			data->in_scaled |= (1 << 8);	/* in8 is Vbat */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
  	/* Initialize the IT87 chip */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1761
  	it87_init_device(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1762
1763
  
  	/* Register sysfs hooks */
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1764
1765
  	err = sysfs_create_group(&dev->kobj, &it87_group);
  	if (err)
b74f3fdd9   corentin.labbe   hwmon: convert it...
1766
  		goto ERROR2;
17d648bf5   Jean Delvare   it87: Add support...
1767

d9b327c31   Jean Delvare   hwmon: (it87) Add...
1768
1769
1770
1771
1772
  	if (sio_data->beep_pin) {
  		err = sysfs_create_group(&dev->kobj, &it87_group_beep);
  		if (err)
  			goto ERROR4;
  	}
9060f8bdd   Jean Delvare   it87: No sysfs fi...
1773
  	/* Do not create fan files for disabled fans */
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1774
  	fan_group = it87_get_fan_group(data);
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1775
  	fan_beep_need_rw = 1;
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1776
1777
1778
1779
1780
1781
  	for (i = 0; i < 5; i++) {
  		if (!(data->has_fan & (1 << i)))
  			continue;
  		err = sysfs_create_group(&dev->kobj, &fan_group[i]);
  		if (err)
  			goto ERROR4;
d9b327c31   Jean Delvare   hwmon: (it87) Add...
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
  
  		if (sio_data->beep_pin) {
  			err = sysfs_create_file(&dev->kobj,
  						it87_attributes_fan_beep[i]);
  			if (err)
  				goto ERROR4;
  			if (!fan_beep_need_rw)
  				continue;
  
  			/* As we have a single beep enable bit for all fans,
  			 * only the first enabled fan has a writable attribute
  			 * for it. */
  			if (sysfs_chmod_file(&dev->kobj,
  					     it87_attributes_fan_beep[i],
  					     S_IRUGO | S_IWUSR))
  				dev_dbg(dev, "chmod +w fan%d_beep failed
  ",
  					i + 1);
  			fan_beep_need_rw = 0;
  		}
17d648bf5   Jean Delvare   it87: Add support...
1802
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
  	if (enable_pwm_interface) {
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1804
1805
1806
1807
1808
1809
  		for (i = 0; i < 3; i++) {
  			if (sio_data->skip_pwm & (1 << i))
  				continue;
  			err = sysfs_create_group(&dev->kobj,
  						 &it87_group_pwm[i]);
  			if (err)
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
1810
  				goto ERROR4;
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
1811
1812
1813
1814
1815
1816
1817
  
  			if (!has_old_autopwm(data))
  				continue;
  			err = sysfs_create_group(&dev->kobj,
  						 &it87_group_autopwm[i]);
  			if (err)
  				goto ERROR4;
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
1818
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
  	}
895ff2676   Jean Delvare   hwmon: (it87) Ver...
1820
  	if (!sio_data->skip_vid) {
303760b44   Jean Delvare   [PATCH] hwmon: hw...
1821
  		data->vrm = vid_which_vrm();
87673dd73   Jean Delvare   it87: Add support...
1822
  		/* VID reading from Super-I/O config space if available */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1823
  		data->vid = sio_data->vid_value;
6a8d7acfb   Jean Delvare   hwmon: (it87) Cre...
1824
1825
  		err = sysfs_create_group(&dev->kobj, &it87_group_vid);
  		if (err)
87808be4f   Jean Delvare   Fix unchecked ret...
1826
1827
  			goto ERROR4;
  	}
738e5e053   Jean Delvare   hwmon: (it87) Exp...
1828
1829
1830
1831
1832
1833
1834
1835
1836
  	/* Export labels for internal sensors */
  	for (i = 0; i < 3; i++) {
  		if (!(sio_data->internal & (1 << i)))
  			continue;
  		err = sysfs_create_file(&dev->kobj,
  					it87_attributes_label[i]);
  		if (err)
  			goto ERROR4;
  	}
1beeffe43   Tony Jones   hwmon: Convert fr...
1837
1838
1839
  	data->hwmon_dev = hwmon_device_register(dev);
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
87808be4f   Jean Delvare   Fix unchecked ret...
1840
  		goto ERROR4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
1842
1843
  	}
  
  	return 0;
87808be4f   Jean Delvare   Fix unchecked ret...
1844
  ERROR4:
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1845
  	it87_remove_files(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
  ERROR2:
b74f3fdd9   corentin.labbe   hwmon: convert it...
1847
  	platform_set_drvdata(pdev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848
1849
  	kfree(data);
  ERROR1:
87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
1850
  	release_region(res->start, IT87_EC_EXTENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
1853
  ERROR0:
  	return err;
  }
b74f3fdd9   corentin.labbe   hwmon: convert it...
1854
  static int __devexit it87_remove(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1856
  	struct it87_data *data = platform_get_drvdata(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1857

1beeffe43   Tony Jones   hwmon: Convert fr...
1858
  	hwmon_device_unregister(data->hwmon_dev);
723a0aa0a   Jean Delvare   hwmon: (it87) Ref...
1859
  	it87_remove_files(&pdev->dev);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1860

87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
1861
  	release_region(data->addr, IT87_EC_EXTENT);
b74f3fdd9   corentin.labbe   hwmon: convert it...
1862
  	platform_set_drvdata(pdev, NULL);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1863
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
1865
1866
  
  	return 0;
  }
7f999aa72   Jean Delvare   hwmon: Simplify t...
1867
  /* Must be called with data->update_lock held, except during initialization.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
1869
     We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
     would slow down the IT87 access and should not be necessary. */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1870
  static int it87_read_value(struct it87_data *data, u8 reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1872
1873
  	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
  	return inb_p(data->addr + IT87_DATA_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
  }
7f999aa72   Jean Delvare   hwmon: Simplify t...
1875
  /* Must be called with data->update_lock held, except during initialization.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
1877
     We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
     would slow down the IT87 access and should not be necessary. */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1878
  static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1879
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1880
1881
  	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
  	outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
1883
1884
  }
  
  /* Return 1 if and only if the PWM interface is safe to use */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1885
  static int __devinit it87_check_pwm(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1887
  	struct it87_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
1890
  	/* Some BIOSes fail to correctly configure the IT87 fans. All fans off
  	 * and polarity set to active low is sign that this is the case so we
  	 * disable pwm control to protect the user. */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1891
  	int tmp = it87_read_value(data, IT87_REG_FAN_CTL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892
1893
1894
1895
1896
1897
1898
1899
1900
  	if ((tmp & 0x87) == 0) {
  		if (fix_pwm_polarity) {
  			/* The user asks us to attempt a chip reconfiguration.
  			 * This means switching to active high polarity and
  			 * inverting all fan speed values. */
  			int i;
  			u8 pwm[3];
  
  			for (i = 0; i < 3; i++)
b74f3fdd9   corentin.labbe   hwmon: convert it...
1901
  				pwm[i] = it87_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
1903
1904
1905
1906
1907
1908
  							 IT87_REG_PWM(i));
  
  			/* If any fan is in automatic pwm mode, the polarity
  			 * might be correct, as suspicious as it seems, so we
  			 * better don't change anything (but still disable the
  			 * PWM interface). */
  			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1909
  				dev_info(dev, "Reconfiguring PWM to "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
1911
  					 "active high polarity
  ");
b74f3fdd9   corentin.labbe   hwmon: convert it...
1912
  				it87_write_value(data, IT87_REG_FAN_CTL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
1914
  						 tmp | 0x87);
  				for (i = 0; i < 3; i++)
b74f3fdd9   corentin.labbe   hwmon: convert it...
1915
  					it87_write_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
1917
1918
1919
  							 IT87_REG_PWM(i),
  							 0x7f & ~pwm[i]);
  				return 1;
  			}
b74f3fdd9   corentin.labbe   hwmon: convert it...
1920
  			dev_info(dev, "PWM configuration is "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
1922
1923
  				 "too broken to be fixed
  ");
  		}
b74f3fdd9   corentin.labbe   hwmon: convert it...
1924
  		dev_info(dev, "Detected broken BIOS "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
1926
1927
1928
  			 "defaults, disabling PWM interface
  ");
  		return 0;
  	} else if (fix_pwm_polarity) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1929
  		dev_info(dev, "PWM configuration looks "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
1933
1934
1935
1936
1937
  			 "sane, won't touch
  ");
  	}
  
  	return 1;
  }
  
  /* Called when we have found a new IT87. */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1938
  static void __devinit it87_init_device(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
  {
591ec6509   Jean Delvare   hwmon: (it87) Che...
1940
  	struct it87_sio_data *sio_data = pdev->dev.platform_data;
b74f3fdd9   corentin.labbe   hwmon: convert it...
1941
  	struct it87_data *data = platform_get_drvdata(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
  	int tmp, i;
591ec6509   Jean Delvare   hwmon: (it87) Che...
1943
  	u8 mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944

b99883dcd   Jean Delvare   hwmon: (it87) Dis...
1945
1946
1947
1948
1949
1950
1951
  	/* For each PWM channel:
  	 * - If it is in automatic mode, setting to manual mode should set
  	 *   the fan to full speed by default.
  	 * - If it is in manual mode, we need a mapping to temperature
  	 *   channels to use when later setting to automatic mode later.
  	 *   Use a 1:1 mapping by default (we are clueless.)
  	 * In both cases, the value can (and should) be changed by the user
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
1952
1953
1954
1955
  	 * prior to switching to a different mode.
  	 * Note that this is no longer needed for the IT8721F and later, as
  	 * these have separate registers for the temperature mapping and the
  	 * manual duty cycle. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
  	for (i = 0; i < 3; i++) {
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
1957
1958
  		data->pwm_temp_map[i] = i;
  		data->pwm_duty[i] = 0x7f;	/* Full speed */
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
1959
  		data->auto_pwm[i][3] = 0x7f;	/* Full speed, hard-coded */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1960
  	}
c5df9b7a7   Jean Delvare   it87: Overwrite b...
1961
1962
1963
1964
1965
1966
  	/* Some chips seem to have default value 0xff for all limit
  	 * registers. For low voltage limits it makes no sense and triggers
  	 * alarms, so change to 0 instead. For high temperature limits, it
  	 * means -1 degree C, which surprisingly doesn't trigger an alarm,
  	 * but is still confusing, so change to 127 degrees C. */
  	for (i = 0; i < 8; i++) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1967
  		tmp = it87_read_value(data, IT87_REG_VIN_MIN(i));
c5df9b7a7   Jean Delvare   it87: Overwrite b...
1968
  		if (tmp == 0xff)
b74f3fdd9   corentin.labbe   hwmon: convert it...
1969
  			it87_write_value(data, IT87_REG_VIN_MIN(i), 0);
c5df9b7a7   Jean Delvare   it87: Overwrite b...
1970
1971
  	}
  	for (i = 0; i < 3; i++) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
1972
  		tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i));
c5df9b7a7   Jean Delvare   it87: Overwrite b...
1973
  		if (tmp == 0xff)
b74f3fdd9   corentin.labbe   hwmon: convert it...
1974
  			it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
c5df9b7a7   Jean Delvare   it87: Overwrite b...
1975
  	}
a00afb97e   Jean Delvare   hwmon: (it87) Don...
1976
1977
1978
1979
  	/* Temperature channels are not forcibly enabled, as they can be
  	 * set to two different sensor types and we can't guess which one
  	 * is correct for a given system. These channels can be enabled at
  	 * run-time through the temp{1-3}_type sysfs accessors if needed. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
1981
  
  	/* Check if voltage monitors are reset manually or by some reason */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1982
  	tmp = it87_read_value(data, IT87_REG_VIN_ENABLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1983
1984
  	if ((tmp & 0xff) == 0) {
  		/* Enable all voltage monitors */
b74f3fdd9   corentin.labbe   hwmon: convert it...
1985
  		it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1986
1987
1988
  	}
  
  	/* Check if tachometers are reset manually or by some reason */
591ec6509   Jean Delvare   hwmon: (it87) Che...
1989
  	mask = 0x70 & ~(sio_data->skip_fan << 4);
b74f3fdd9   corentin.labbe   hwmon: convert it...
1990
  	data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL);
591ec6509   Jean Delvare   hwmon: (it87) Che...
1991
  	if ((data->fan_main_ctrl & mask) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1992
  		/* Enable all fan tachometers */
591ec6509   Jean Delvare   hwmon: (it87) Che...
1993
  		data->fan_main_ctrl |= mask;
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
1994
1995
  		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
  				 data->fan_main_ctrl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1996
  	}
9060f8bdd   Jean Delvare   it87: No sysfs fi...
1997
  	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998

17d648bf5   Jean Delvare   it87: Add support...
1999
  	/* Set tachometers to 16-bit mode if needed */
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
2000
  	if (has_16bit_fans(data)) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2001
  		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
9060f8bdd   Jean Delvare   it87: No sysfs fi...
2002
  		if (~tmp & 0x07 & data->has_fan) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2003
  			dev_dbg(&pdev->dev,
17d648bf5   Jean Delvare   it87: Add support...
2004
2005
  				"Setting fan1-3 to 16-bit mode
  ");
b74f3fdd9   corentin.labbe   hwmon: convert it...
2006
  			it87_write_value(data, IT87_REG_FAN_16BIT,
17d648bf5   Jean Delvare   it87: Add support...
2007
2008
  					 tmp | 0x07);
  		}
816d8c6a2   Andrew Paprocki   hwmon: (it87) Sup...
2009
2010
2011
2012
2013
2014
2015
  		/* IT8705F only supports three fans. */
  		if (data->type != it87) {
  			if (tmp & (1 << 4))
  				data->has_fan |= (1 << 3); /* fan4 enabled */
  			if (tmp & (1 << 5))
  				data->has_fan |= (1 << 4); /* fan5 enabled */
  		}
17d648bf5   Jean Delvare   it87: Add support...
2016
  	}
591ec6509   Jean Delvare   hwmon: (it87) Che...
2017
2018
  	/* Fan input pins may be used for alternative functions */
  	data->has_fan &= ~sio_data->skip_fan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2019
  	/* Start monitoring */
b74f3fdd9   corentin.labbe   hwmon: convert it...
2020
2021
  	it87_write_value(data, IT87_REG_CONFIG,
  			 (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
2023
  			 | (update_vbat ? 0x41 : 0x01));
  }
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
2024
2025
2026
  static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
  {
  	data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
2027
  	if (data->type == it8721) {
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
2028
  		data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
6229cdb23   Jean Delvare   hwmon: (it87) Fix...
2029
2030
2031
2032
2033
2034
2035
2036
  		data->pwm_duty[nr] = it87_read_value(data,
  						     IT87_REG_PWM_DUTY(nr));
  	} else {
  		if (data->pwm_ctrl[nr] & 0x80)	/* Automatic mode */
  			data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
  		else				/* Manual mode */
  			data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
  	}
4f3f51bc2   Jean Delvare   hwmon: (it87) Add...
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
  
  	if (has_old_autopwm(data)) {
  		int i;
  
  		for (i = 0; i < 5 ; i++)
  			data->auto_temp[nr][i] = it87_read_value(data,
  						IT87_REG_AUTO_TEMP(nr, i));
  		for (i = 0; i < 3 ; i++)
  			data->auto_pwm[nr][i] = it87_read_value(data,
  						IT87_REG_AUTO_PWM(nr, i));
  	}
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
2048
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
2050
  static struct it87_data *it87_update_device(struct device *dev)
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2051
  	struct it87_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
  	int i;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
2053
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
2055
2056
  
  	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
  	    || !data->valid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2057
2058
  		if (update_vbat) {
  			/* Cleared after each update, so reenable.  Value
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2059
  			   returned by this read will be previous value */
b74f3fdd9   corentin.labbe   hwmon: convert it...
2060
  			it87_write_value(data, IT87_REG_CONFIG,
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2061
  				it87_read_value(data, IT87_REG_CONFIG) | 0x40);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2062
2063
2064
  		}
  		for (i = 0; i <= 7; i++) {
  			data->in[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2065
  				it87_read_value(data, IT87_REG_VIN(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2066
  			data->in_min[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2067
  				it87_read_value(data, IT87_REG_VIN_MIN(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068
  			data->in_max[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2069
  				it87_read_value(data, IT87_REG_VIN_MAX(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
  		}
3543a53f6   Jean Delvare   it87: in8 has no ...
2071
  		/* in8 (battery) has no limit registers */
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2072
  		data->in[8] = it87_read_value(data, IT87_REG_VIN(8));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2073

c7f1f7166   Jean Delvare   hwmon: (it87) Add...
2074
  		for (i = 0; i < 5; i++) {
9060f8bdd   Jean Delvare   it87: No sysfs fi...
2075
2076
2077
  			/* Skip disabled fans */
  			if (!(data->has_fan & (1 << i)))
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
  			data->fan_min[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2079
  				it87_read_value(data, IT87_REG_FAN_MIN[i]);
b74f3fdd9   corentin.labbe   hwmon: convert it...
2080
  			data->fan[i] = it87_read_value(data,
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
2081
  				       IT87_REG_FAN[i]);
17d648bf5   Jean Delvare   it87: Add support...
2082
  			/* Add high byte if in 16-bit mode */
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
2083
  			if (has_16bit_fans(data)) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2084
  				data->fan[i] |= it87_read_value(data,
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
2085
  						IT87_REG_FANX[i]) << 8;
b74f3fdd9   corentin.labbe   hwmon: convert it...
2086
  				data->fan_min[i] |= it87_read_value(data,
c7f1f7166   Jean Delvare   hwmon: (it87) Add...
2087
  						IT87_REG_FANX_MIN[i]) << 8;
17d648bf5   Jean Delvare   it87: Add support...
2088
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
2090
2091
  		}
  		for (i = 0; i < 3; i++) {
  			data->temp[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2092
  				it87_read_value(data, IT87_REG_TEMP(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2093
  			data->temp_high[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2094
  				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2095
  			data->temp_low[i] =
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2096
  				it87_read_value(data, IT87_REG_TEMP_LOW(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
  		}
17d648bf5   Jean Delvare   it87: Add support...
2098
  		/* Newer chips don't have clock dividers */
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
2099
  		if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2100
  			i = it87_read_value(data, IT87_REG_FAN_DIV);
17d648bf5   Jean Delvare   it87: Add support...
2101
2102
2103
2104
  			data->fan_div[0] = i & 0x07;
  			data->fan_div[1] = (i >> 3) & 0x07;
  			data->fan_div[2] = (i & 0x40) ? 3 : 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2105
2106
  
  		data->alarms =
b74f3fdd9   corentin.labbe   hwmon: convert it...
2107
2108
2109
  			it87_read_value(data, IT87_REG_ALARM1) |
  			(it87_read_value(data, IT87_REG_ALARM2) << 8) |
  			(it87_read_value(data, IT87_REG_ALARM3) << 16);
d9b327c31   Jean Delvare   hwmon: (it87) Add...
2110
  		data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
2111

b74f3fdd9   corentin.labbe   hwmon: convert it...
2112
2113
2114
  		data->fan_main_ctrl = it87_read_value(data,
  				IT87_REG_FAN_MAIN_CTRL);
  		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
b99883dcd   Jean Delvare   hwmon: (it87) Dis...
2115
2116
  		for (i = 0; i < 3; i++)
  			it87_update_pwm_ctrl(data, i);
b74f3fdd9   corentin.labbe   hwmon: convert it...
2117
2118
  
  		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
0475169c1   Andrew Paprocki   hwmon: (it87) Sup...
2119
  		/* The 8705 does not have VID capability.
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
2120
  		   The 8718 and later don't use IT87_REG_VID for the
b4da93e4b   Jean-Marc Spaggiari   hwmon: (it87) Add...
2121
  		   same purpose. */
17d648bf5   Jean Delvare   it87: Add support...
2122
  		if (data->type == it8712 || data->type == it8716) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2123
  			data->vid = it87_read_value(data, IT87_REG_VID);
17d648bf5   Jean Delvare   it87: Add support...
2124
2125
2126
  			/* The older IT8712F revisions had only 5 VID pins,
  			   but we assume it is always safe to read 6 bits. */
  			data->vid &= 0x3f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2127
2128
2129
2130
  		}
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
2131
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
2133
2134
  
  	return data;
  }
b74f3fdd9   corentin.labbe   hwmon: convert it...
2135
2136
2137
2138
  static int __init it87_device_add(unsigned short address,
  				  const struct it87_sio_data *sio_data)
  {
  	struct resource res = {
87b4b6634   Bjorn Helgaas   hwmon: (it87) req...
2139
2140
  		.start	= address + IT87_EC_OFFSET,
  		.end	= address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1,
b74f3fdd9   corentin.labbe   hwmon: convert it...
2141
2142
2143
2144
  		.name	= DRVNAME,
  		.flags	= IORESOURCE_IO,
  	};
  	int err;
b9acb64a3   Jean Delvare   hwmon: Check for ...
2145
2146
2147
  	err = acpi_check_resource_conflict(&res);
  	if (err)
  		goto exit;
b74f3fdd9   corentin.labbe   hwmon: convert it...
2148
2149
2150
  	pdev = platform_device_alloc(DRVNAME, address);
  	if (!pdev) {
  		err = -ENOMEM;
a8ca10379   Joe Perches   hwmon: (it87) Use...
2151
2152
  		pr_err("Device allocation failed
  ");
b74f3fdd9   corentin.labbe   hwmon: convert it...
2153
2154
2155
2156
2157
  		goto exit;
  	}
  
  	err = platform_device_add_resources(pdev, &res, 1);
  	if (err) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
2158
2159
  		pr_err("Device resource addition failed (%d)
  ", err);
b74f3fdd9   corentin.labbe   hwmon: convert it...
2160
2161
2162
2163
2164
2165
  		goto exit_device_put;
  	}
  
  	err = platform_device_add_data(pdev, sio_data,
  				       sizeof(struct it87_sio_data));
  	if (err) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
2166
2167
  		pr_err("Platform data allocation failed
  ");
b74f3fdd9   corentin.labbe   hwmon: convert it...
2168
2169
2170
2171
2172
  		goto exit_device_put;
  	}
  
  	err = platform_device_add(pdev);
  	if (err) {
a8ca10379   Joe Perches   hwmon: (it87) Use...
2173
2174
  		pr_err("Device addition failed (%d)
  ", err);
b74f3fdd9   corentin.labbe   hwmon: convert it...
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
  		goto exit_device_put;
  	}
  
  	return 0;
  
  exit_device_put:
  	platform_device_put(pdev);
  exit:
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2185
2186
  static int __init sm_it87_init(void)
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2187
  	int err;
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2188
  	unsigned short isa_address = 0;
b74f3fdd9   corentin.labbe   hwmon: convert it...
2189
  	struct it87_sio_data sio_data;
98dd22c3e   Jean Delvare   hwmon: (it87) Pre...
2190
  	memset(&sio_data, 0, sizeof(struct it87_sio_data));
b74f3fdd9   corentin.labbe   hwmon: convert it...
2191
2192
2193
2194
2195
2196
  	err = it87_find(&isa_address, &sio_data);
  	if (err)
  		return err;
  	err = platform_driver_register(&it87_driver);
  	if (err)
  		return err;
fde095090   Jean Delvare   [PATCH] I2C: Sepa...
2197

b74f3fdd9   corentin.labbe   hwmon: convert it...
2198
  	err = it87_device_add(isa_address, &sio_data);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2199
  	if (err) {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2200
2201
2202
2203
2204
  		platform_driver_unregister(&it87_driver);
  		return err;
  	}
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2205
2206
2207
2208
  }
  
  static void __exit sm_it87_exit(void)
  {
b74f3fdd9   corentin.labbe   hwmon: convert it...
2209
2210
  	platform_device_unregister(pdev);
  	platform_driver_unregister(&it87_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2211
  }
f1d8e3326   Jean Delvare   hwmon: (it87) Dis...
2212
  MODULE_AUTHOR("Chris Gauthron, "
b19367c6f   Jean Delvare   it87: Copyright u...
2213
  	      "Jean Delvare <khali@linux-fr.org>");
44c1bcd4b   Jean Delvare   hwmon: (it87) Add...
2214
  MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2215
2216
2217
  module_param(update_vbat, bool, 0);
  MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
  module_param(fix_pwm_polarity, bool, 0);
5f2dc798c   Jean Delvare   hwmon: (it87) Fix...
2218
2219
  MODULE_PARM_DESC(fix_pwm_polarity,
  		 "Force PWM polarity to active high (DANGEROUS)");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2220
2221
2222
2223
  MODULE_LICENSE("GPL");
  
  module_init(sm_it87_init);
  module_exit(sm_it87_exit);