blob: ed25e4bab97818955c4ada227d983cabb1fe5530 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jean Delvare5f2dc792010-03-05 22:17:18 +01002 * it87.c - Part of lm_sensors, Linux kernel modules for hardware
3 * monitoring.
4 *
5 * The IT8705F is an LPC-based Super I/O part that contains UARTs, a
6 * parallel port, an IR port, a MIDI port, a floppy controller, etc., in
7 * addition to an Environment Controller (Enhanced Hardware Monitor and
8 * Fan Controller)
9 *
10 * This driver supports only the Environment Controller in the IT8705F and
11 * similar parts. The other devices are supported by different drivers.
12 *
Rudolf Marekc145d5c2014-01-29 20:40:08 +010013 * Supports: IT8603E Super I/O chip w/LPC interface
Rudolf Marek574e9bd2014-04-04 18:01:35 +020014 * IT8623E Super I/O chip w/LPC interface
Rudolf Marekc145d5c2014-01-29 20:40:08 +010015 * IT8705F Super I/O chip w/LPC interface
Jean Delvare5f2dc792010-03-05 22:17:18 +010016 * IT8712F Super I/O chip w/LPC interface
17 * IT8716F Super I/O chip w/LPC interface
18 * IT8718F Super I/O chip w/LPC interface
19 * IT8720F Super I/O chip w/LPC interface
Jean Delvare44c1bcd2010-10-28 20:31:51 +020020 * IT8721F Super I/O chip w/LPC interface
Jean Delvare5f2dc792010-03-05 22:17:18 +010021 * IT8726F Super I/O chip w/LPC interface
Jean Delvare16b5dda2012-01-16 22:51:48 +010022 * IT8728F Super I/O chip w/LPC interface
Jean Delvare44c1bcd2010-10-28 20:31:51 +020023 * IT8758E Super I/O chip w/LPC interface
Guenter Roeckb0636702012-09-07 17:34:41 -060024 * IT8771E Super I/O chip w/LPC interface
25 * IT8772E Super I/O chip w/LPC interface
Guenter Roeck7bc32d22015-01-17 14:10:24 -080026 * IT8781F Super I/O chip w/LPC interface
Guenter Roeck0531d982012-03-02 11:46:44 -080027 * IT8782F Super I/O chip w/LPC interface
28 * IT8783E/F Super I/O chip w/LPC interface
Jean Delvare5f2dc792010-03-05 22:17:18 +010029 * Sis950 A clone of the IT8705F
30 *
31 * Copyright (C) 2001 Chris Gauthron
Jean Delvare7c81c602014-01-29 20:40:08 +010032 * Copyright (C) 2005-2010 Jean Delvare <jdelvare@suse.de>
Jean Delvare5f2dc792010-03-05 22:17:18 +010033 *
34 * This program is free software; you can redistribute it and/or modify
35 * it under the terms of the GNU General Public License as published by
36 * the Free Software Foundation; either version 2 of the License, or
37 * (at your option) any later version.
38 *
39 * This program is distributed in the hope that it will be useful,
40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 * GNU General Public License for more details.
43 *
44 * You should have received a copy of the GNU General Public License
45 * along with this program; if not, write to the Free Software
46 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
47 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Joe Perchesa8ca1032011-01-12 21:55:10 +010049#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/module.h>
52#include <linux/init.h>
53#include <linux/slab.h>
54#include <linux/jiffies.h>
corentin.labbeb74f3fd2007-06-13 20:27:36 +020055#include <linux/platform_device.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040056#include <linux/hwmon.h>
Jean Delvare303760b2005-07-31 21:52:01 +020057#include <linux/hwmon-sysfs.h>
58#include <linux/hwmon-vid.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040059#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010060#include <linux/mutex.h>
Jean Delvare87808be2006-09-24 21:17:13 +020061#include <linux/sysfs.h>
Jean Delvare98dd22c2008-10-09 15:33:58 +020062#include <linux/string.h>
63#include <linux/dmi.h>
Jean Delvareb9acb642009-01-07 16:37:35 +010064#include <linux/acpi.h>
H Hartley Sweeten6055fae2009-09-15 17:18:13 +020065#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
corentin.labbeb74f3fd2007-06-13 20:27:36 +020067#define DRVNAME "it87"
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Guenter Roeckb0636702012-09-07 17:34:41 -060069enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
Guenter Roeck7bc32d22015-01-17 14:10:24 -080070 it8772, it8781, it8782, it8783, it8603 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Jean Delvare67b671b2007-12-06 23:13:42 +010072static unsigned short force_id;
73module_param(force_id, ushort, 0);
74MODULE_PARM_DESC(force_id, "Override the detected device ID");
75
corentin.labbeb74f3fd2007-06-13 20:27:36 +020076static struct platform_device *pdev;
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078#define REG 0x2e /* The register to read/write */
79#define DEV 0x07 /* Register: Logical device select */
80#define VAL 0x2f /* The value to read/write */
81#define PME 0x04 /* The device with the fan registers in it */
Jean-Marc Spaggiarib4da93e2009-01-07 16:37:32 +010082
83/* The device with the IT8718F/IT8720F VID value in it */
84#define GPIO 0x07
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#define DEVID 0x20 /* Register: Device ID */
87#define DEVREV 0x22 /* Register: Device Revision */
88
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +020089static inline int superio_inb(int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
91 outb(reg, REG);
92 return inb(VAL);
93}
94
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +020095static inline void superio_outb(int reg, int val)
Jean Delvare436cad22010-07-09 16:22:48 +020096{
97 outb(reg, REG);
98 outb(val, VAL);
99}
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101static int superio_inw(int reg)
102{
103 int val;
104 outb(reg++, REG);
105 val = inb(VAL) << 8;
106 outb(reg, REG);
107 val |= inb(VAL);
108 return val;
109}
110
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200111static inline void superio_select(int ldn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112{
113 outb(DEV, REG);
Jean Delvare87673dd2006-08-28 14:37:19 +0200114 outb(ldn, VAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200117static inline int superio_enter(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200119 /*
120 * Try to reserve REG and REG + 1 for exclusive access.
121 */
122 if (!request_muxed_region(REG, 2, DRVNAME))
123 return -EBUSY;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 outb(0x87, REG);
126 outb(0x01, REG);
127 outb(0x55, REG);
128 outb(0x55, REG);
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200129 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200132static inline void superio_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
134 outb(0x02, REG);
135 outb(0x02, VAL);
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +0200136 release_region(REG, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138
Jean Delvare87673dd2006-08-28 14:37:19 +0200139/* Logical device 4 registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140#define IT8712F_DEVID 0x8712
141#define IT8705F_DEVID 0x8705
Jean Delvare17d648b2006-08-28 14:23:46 +0200142#define IT8716F_DEVID 0x8716
Jean Delvare87673dd2006-08-28 14:37:19 +0200143#define IT8718F_DEVID 0x8718
Jean-Marc Spaggiarib4da93e2009-01-07 16:37:32 +0100144#define IT8720F_DEVID 0x8720
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200145#define IT8721F_DEVID 0x8721
Rudolf Marek08a8f6e2007-06-09 10:11:16 -0400146#define IT8726F_DEVID 0x8726
Jean Delvare16b5dda2012-01-16 22:51:48 +0100147#define IT8728F_DEVID 0x8728
Guenter Roeckb0636702012-09-07 17:34:41 -0600148#define IT8771E_DEVID 0x8771
149#define IT8772E_DEVID 0x8772
Guenter Roeck7bc32d22015-01-17 14:10:24 -0800150#define IT8781F_DEVID 0x8781
Guenter Roeck0531d982012-03-02 11:46:44 -0800151#define IT8782F_DEVID 0x8782
152#define IT8783E_DEVID 0x8783
Rudolf Marek7183ae82014-04-04 18:01:35 +0200153#define IT8603E_DEVID 0x8603
Rudolf Marek574e9bd2014-04-04 18:01:35 +0200154#define IT8623E_DEVID 0x8623
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define IT87_ACT_REG 0x30
156#define IT87_BASE_REG 0x60
157
Jean Delvare87673dd2006-08-28 14:37:19 +0200158/* Logical device 7 registers (IT8712F and later) */
Guenter Roeck0531d982012-03-02 11:46:44 -0800159#define IT87_SIO_GPIO1_REG 0x25
Jean Delvare895ff262009-12-09 20:35:47 +0100160#define IT87_SIO_GPIO3_REG 0x27
Jean Delvare591ec652009-12-09 20:35:48 +0100161#define IT87_SIO_GPIO5_REG 0x29
Guenter Roeck0531d982012-03-02 11:46:44 -0800162#define IT87_SIO_PINX1_REG 0x2a /* Pin selection */
Jean Delvare87673dd2006-08-28 14:37:19 +0200163#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
Guenter Roeck0531d982012-03-02 11:46:44 -0800164#define IT87_SIO_SPI_REG 0xef /* SPI function pin select */
Jean Delvare87673dd2006-08-28 14:37:19 +0200165#define IT87_SIO_VID_REG 0xfc /* VID value */
Jean Delvared9b327c2010-03-05 22:17:17 +0100166#define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */
Jean Delvare87673dd2006-08-28 14:37:19 +0200167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168/* Update battery voltage after every reading if true */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030169static bool update_vbat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171/* Not all BIOSes properly configure the PWM registers */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030172static bool fix_pwm_polarity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174/* Many IT87 constants specified below */
175
176/* Length of ISA address segment */
177#define IT87_EXTENT 8
178
Bjorn Helgaas87b4b662008-01-22 07:21:03 -0500179/* Length of ISA address segment for Environmental Controller */
180#define IT87_EC_EXTENT 2
181
182/* Offset of EC registers from ISA base address */
183#define IT87_EC_OFFSET 5
184
185/* Where are the ISA address/data registers relative to the EC base address */
186#define IT87_ADDR_REG_OFFSET 0
187#define IT87_DATA_REG_OFFSET 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
189/*----- The IT87 registers -----*/
190
191#define IT87_REG_CONFIG 0x00
192
193#define IT87_REG_ALARM1 0x01
194#define IT87_REG_ALARM2 0x02
195#define IT87_REG_ALARM3 0x03
196
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800197/*
198 * The IT8718F and IT8720F have the VID value in a different register, in
199 * Super-I/O configuration space.
200 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201#define IT87_REG_VID 0x0a
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800202/*
203 * The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
204 * for fan divisors. Later IT8712F revisions must use 16-bit tachometer
205 * mode.
206 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207#define IT87_REG_FAN_DIV 0x0b
Jean Delvare17d648b2006-08-28 14:23:46 +0200208#define IT87_REG_FAN_16BIT 0x0c
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
211
Jean Delvarec7f1f712007-09-03 17:11:46 +0200212static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
213static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 };
214static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 };
215static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
Guenter Roeck161d8982012-12-19 22:17:01 +0100216static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
217
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218#define IT87_REG_FAN_MAIN_CTRL 0x13
219#define IT87_REG_FAN_CTL 0x14
220#define IT87_REG_PWM(nr) (0x15 + (nr))
Jean Delvare6229cdb2010-12-08 16:27:22 +0100221#define IT87_REG_PWM_DUTY(nr) (0x63 + (nr) * 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223#define IT87_REG_VIN(nr) (0x20 + (nr))
224#define IT87_REG_TEMP(nr) (0x29 + (nr))
225
226#define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2)
227#define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2)
228#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
229#define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2)
230
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231#define IT87_REG_VIN_ENABLE 0x50
232#define IT87_REG_TEMP_ENABLE 0x51
Guenter Roeck4573acb2012-03-26 16:17:41 -0700233#define IT87_REG_TEMP_EXTRA 0x55
Jean Delvared9b327c2010-03-05 22:17:17 +0100234#define IT87_REG_BEEP_ENABLE 0x5c
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
236#define IT87_REG_CHIPID 0x58
237
Jean Delvare4f3f51b2010-03-05 22:17:21 +0100238#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
239#define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i))
240
Guenter Roeck483db432012-12-19 22:17:02 +0100241struct it87_devices {
242 const char *name;
243 u16 features;
Guenter Roeck19529782012-12-19 22:17:02 +0100244 u8 peci_mask;
245 u8 old_peci_mask;
Guenter Roeck483db432012-12-19 22:17:02 +0100246};
247
248#define FEAT_12MV_ADC (1 << 0)
249#define FEAT_NEWER_AUTOPWM (1 << 1)
250#define FEAT_OLD_AUTOPWM (1 << 2)
251#define FEAT_16BIT_FANS (1 << 3)
252#define FEAT_TEMP_OFFSET (1 << 4)
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100253#define FEAT_TEMP_PECI (1 << 5)
Guenter Roeck19529782012-12-19 22:17:02 +0100254#define FEAT_TEMP_OLD_PECI (1 << 6)
Guenter Roeck483db432012-12-19 22:17:02 +0100255
256static const struct it87_devices it87_devices[] = {
257 [it87] = {
258 .name = "it87",
259 .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */
260 },
261 [it8712] = {
262 .name = "it8712",
263 .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */
264 },
265 [it8716] = {
266 .name = "it8716",
267 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET,
268 },
269 [it8718] = {
270 .name = "it8718",
Guenter Roeck19529782012-12-19 22:17:02 +0100271 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
272 | FEAT_TEMP_OLD_PECI,
273 .old_peci_mask = 0x4,
Guenter Roeck483db432012-12-19 22:17:02 +0100274 },
275 [it8720] = {
276 .name = "it8720",
Guenter Roeck19529782012-12-19 22:17:02 +0100277 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
278 | FEAT_TEMP_OLD_PECI,
279 .old_peci_mask = 0x4,
Guenter Roeck483db432012-12-19 22:17:02 +0100280 },
281 [it8721] = {
282 .name = "it8721",
283 .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
Guenter Roeck19529782012-12-19 22:17:02 +0100284 | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI,
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100285 .peci_mask = 0x05,
Guenter Roeck19529782012-12-19 22:17:02 +0100286 .old_peci_mask = 0x02, /* Actually reports PCH */
Guenter Roeck483db432012-12-19 22:17:02 +0100287 },
288 [it8728] = {
289 .name = "it8728",
290 .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100291 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
292 .peci_mask = 0x07,
Guenter Roeck483db432012-12-19 22:17:02 +0100293 },
Guenter Roeckb0636702012-09-07 17:34:41 -0600294 [it8771] = {
295 .name = "it8771",
296 .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
297 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
298 /* PECI: guesswork */
299 /* 12mV ADC (OHM) */
300 /* 16 bit fans (OHM) */
301 .peci_mask = 0x07,
302 },
303 [it8772] = {
304 .name = "it8772",
305 .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
306 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
307 /* PECI (coreboot) */
308 /* 12mV ADC (HWSensors4, OHM) */
309 /* 16 bit fans (HWSensors4, OHM) */
310 .peci_mask = 0x07,
311 },
Guenter Roeck7bc32d22015-01-17 14:10:24 -0800312 [it8781] = {
313 .name = "it8781",
314 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
315 | FEAT_TEMP_OLD_PECI,
316 .old_peci_mask = 0x4,
317 },
Guenter Roeck483db432012-12-19 22:17:02 +0100318 [it8782] = {
319 .name = "it8782",
Guenter Roeck19529782012-12-19 22:17:02 +0100320 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
321 | FEAT_TEMP_OLD_PECI,
322 .old_peci_mask = 0x4,
Guenter Roeck483db432012-12-19 22:17:02 +0100323 },
324 [it8783] = {
325 .name = "it8783",
Guenter Roeck19529782012-12-19 22:17:02 +0100326 .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
327 | FEAT_TEMP_OLD_PECI,
328 .old_peci_mask = 0x4,
Guenter Roeck483db432012-12-19 22:17:02 +0100329 },
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100330 [it8603] = {
331 .name = "it8603",
332 .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
333 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
334 .peci_mask = 0x07,
335 },
Guenter Roeck483db432012-12-19 22:17:02 +0100336};
337
338#define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS)
339#define has_12mv_adc(data) ((data)->features & FEAT_12MV_ADC)
340#define has_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM)
341#define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM)
342#define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET)
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100343#define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \
344 ((data)->peci_mask & (1 << nr)))
Guenter Roeck19529782012-12-19 22:17:02 +0100345#define has_temp_old_peci(data, nr) \
346 (((data)->features & FEAT_TEMP_OLD_PECI) && \
347 ((data)->old_peci_mask & (1 << nr)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200349struct it87_sio_data {
350 enum chips type;
351 /* Values read from Super-I/O config space */
Andrew Paprocki04751692008-08-06 22:41:06 +0200352 u8 revision;
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200353 u8 vid_value;
Jean Delvared9b327c2010-03-05 22:17:17 +0100354 u8 beep_pin;
Jean Delvare738e5e02010-08-14 21:08:50 +0200355 u8 internal; /* Internal sensors can be labeled */
Jean Delvare591ec652009-12-09 20:35:48 +0100356 /* Features skipped based on config or DMI */
Guenter Roeck9172b5d2012-03-24 21:49:54 -0700357 u16 skip_in;
Jean Delvare895ff262009-12-09 20:35:47 +0100358 u8 skip_vid;
Jean Delvare591ec652009-12-09 20:35:48 +0100359 u8 skip_fan;
Jean Delvare98dd22c2008-10-09 15:33:58 +0200360 u8 skip_pwm;
Guenter Roeck4573acb2012-03-26 16:17:41 -0700361 u8 skip_temp;
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200362};
363
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800364/*
365 * For each registered chip, we need to keep some data in memory.
366 * The structure is dynamically allocated.
367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368struct it87_data {
Tony Jones1beeffe2007-08-20 13:46:20 -0700369 struct device *hwmon_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 enum chips type;
Guenter Roeck483db432012-12-19 22:17:02 +0100371 u16 features;
Guenter Roeck19529782012-12-19 22:17:02 +0100372 u8 peci_mask;
373 u8 old_peci_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200375 unsigned short addr;
376 const char *name;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100377 struct mutex update_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 char valid; /* !=0 if following fields are valid */
379 unsigned long last_updated; /* In jiffies */
380
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200381 u16 in_scaled; /* Internal voltage sensors are scaled */
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100382 u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */
Jean Delvare9060f8b2006-08-28 14:24:17 +0200383 u8 has_fan; /* Bitfield, fans enabled */
Guenter Roecke1169ba2012-12-19 22:17:01 +0100384 u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */
Guenter Roeck4573acb2012-03-26 16:17:41 -0700385 u8 has_temp; /* Bitfield, temp sensors enabled */
Guenter Roeck161d8982012-12-19 22:17:01 +0100386 s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
Guenter Roeck19529782012-12-19 22:17:02 +0100387 u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */
388 u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 u8 fan_div[3]; /* Register encoding, shifted right */
390 u8 vid; /* Register encoding, combined */
Jean Delvarea7be58a2005-12-18 16:40:14 +0100391 u8 vrm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 u32 alarms; /* Register encoding, combined */
Jean Delvared9b327c2010-03-05 22:17:17 +0100393 u8 beeps; /* Register encoding */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 u8 fan_main_ctrl; /* Register value */
Jean Delvaref8d0c192007-02-14 21:15:02 +0100395 u8 fan_ctl; /* Register value */
Jean Delvareb99883d2010-03-05 22:17:15 +0100396
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800397 /*
398 * The following 3 arrays correspond to the same registers up to
Jean Delvare6229cdb2010-12-08 16:27:22 +0100399 * the IT8720F. The meaning of bits 6-0 depends on the value of bit
400 * 7, and we want to preserve settings on mode changes, so we have
401 * to track all values separately.
402 * Starting with the IT8721F, the manual PWM duty cycles are stored
403 * in separate registers (8-bit values), so the separate tracking
404 * is no longer needed, but it is still done to keep the driver
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800405 * simple.
406 */
Jean Delvareb99883d2010-03-05 22:17:15 +0100407 u8 pwm_ctrl[3]; /* Register value */
Jean Delvare6229cdb2010-12-08 16:27:22 +0100408 u8 pwm_duty[3]; /* Manual PWM value set by user */
Jean Delvareb99883d2010-03-05 22:17:15 +0100409 u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */
Jean Delvare4f3f51b2010-03-05 22:17:21 +0100410
411 /* Automatic fan speed control registers */
412 u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */
413 s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414};
415
Guenter Roeck0531d982012-03-02 11:46:44 -0800416static int adc_lsb(const struct it87_data *data, int nr)
417{
418 int lsb = has_12mv_adc(data) ? 12 : 16;
419 if (data->in_scaled & (1 << nr))
420 lsb <<= 1;
421 return lsb;
422}
423
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200424static u8 in_to_reg(const struct it87_data *data, int nr, long val)
425{
Guenter Roeck0531d982012-03-02 11:46:44 -0800426 val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
Guenter Roeck2a844c12013-01-09 08:09:34 -0800427 return clamp_val(val, 0, 255);
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200428}
429
430static int in_from_reg(const struct it87_data *data, int nr, int val)
431{
Guenter Roeck0531d982012-03-02 11:46:44 -0800432 return val * adc_lsb(data, nr);
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200433}
Jean Delvare0df6454d2010-10-28 20:31:51 +0200434
435static inline u8 FAN_TO_REG(long rpm, int div)
436{
437 if (rpm == 0)
438 return 255;
Guenter Roeck2a844c12013-01-09 08:09:34 -0800439 rpm = clamp_val(rpm, 1, 1000000);
440 return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
Jean Delvare0df6454d2010-10-28 20:31:51 +0200441}
442
443static inline u16 FAN16_TO_REG(long rpm)
444{
445 if (rpm == 0)
446 return 0xffff;
Guenter Roeck2a844c12013-01-09 08:09:34 -0800447 return clamp_val((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
Jean Delvare0df6454d2010-10-28 20:31:51 +0200448}
449
450#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \
451 1350000 / ((val) * (div)))
452/* The divider is fixed to 2 in 16-bit mode */
453#define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
454 1350000 / ((val) * 2))
455
Guenter Roeck2a844c12013-01-09 08:09:34 -0800456#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (((val) - 500) / 1000) : \
457 ((val) + 500) / 1000), -128, 127))
Jean Delvare0df6454d2010-10-28 20:31:51 +0200458#define TEMP_FROM_REG(val) ((val) * 1000)
459
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200460static u8 pwm_to_reg(const struct it87_data *data, long val)
461{
Jean Delvare16b5dda2012-01-16 22:51:48 +0100462 if (has_newer_autopwm(data))
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200463 return val;
464 else
465 return val >> 1;
466}
467
468static int pwm_from_reg(const struct it87_data *data, u8 reg)
469{
Jean Delvare16b5dda2012-01-16 22:51:48 +0100470 if (has_newer_autopwm(data))
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200471 return reg;
472 else
473 return (reg & 0x7f) << 1;
474}
475
Jean Delvare0df6454d2010-10-28 20:31:51 +0200476
477static int DIV_TO_REG(int val)
478{
479 int answer = 0;
480 while (answer < 7 && (val >>= 1))
481 answer++;
482 return answer;
483}
484#define DIV_FROM_REG(val) (1 << (val))
485
486static const unsigned int pwm_freq[8] = {
487 48000000 / 128,
488 24000000 / 128,
489 12000000 / 128,
490 8000000 / 128,
491 6000000 / 128,
492 3000000 / 128,
493 1500000 / 128,
494 750000 / 128,
495};
496
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200497static int it87_probe(struct platform_device *pdev);
Bill Pemberton281dfd02012-11-19 13:25:51 -0500498static int it87_remove(struct platform_device *pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200500static int it87_read_value(struct it87_data *data, u8 reg);
501static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502static struct it87_data *it87_update_device(struct device *dev);
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200503static int it87_check_pwm(struct device *dev);
504static void it87_init_device(struct platform_device *pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200507static struct platform_driver it87_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100508 .driver = {
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200509 .name = DRVNAME,
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100510 },
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200511 .probe = it87_probe,
Bill Pemberton9e5e9b72012-11-19 13:21:20 -0500512 .remove = it87_remove,
Jean Delvarefde09502005-07-19 23:51:07 +0200513};
514
Jean Delvare20ad93d2005-06-05 11:53:25 +0200515static ssize_t show_in(struct device *dev, struct device_attribute *attr,
Guenter Roeck929c6a52012-12-19 22:17:00 +0100516 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
Guenter Roeck929c6a52012-12-19 22:17:00 +0100518 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
519 int nr = sattr->nr;
520 int index = sattr->index;
Jean Delvare20ad93d2005-06-05 11:53:25 +0200521
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 struct it87_data *data = it87_update_device(dev);
Guenter Roeck929c6a52012-12-19 22:17:00 +0100523 return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524}
525
Guenter Roeck929c6a52012-12-19 22:17:00 +0100526static ssize_t set_in(struct device *dev, struct device_attribute *attr,
527 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528{
Guenter Roeck929c6a52012-12-19 22:17:00 +0100529 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
530 int nr = sattr->nr;
531 int index = sattr->index;
Jean Delvare20ad93d2005-06-05 11:53:25 +0200532
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200533 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100534 unsigned long val;
535
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100536 if (kstrtoul(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +0100537 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100539 mutex_lock(&data->update_lock);
Guenter Roeck929c6a52012-12-19 22:17:00 +0100540 data->in[nr][index] = in_to_reg(data, nr, val);
541 it87_write_value(data,
542 index == 1 ? IT87_REG_VIN_MIN(nr)
543 : IT87_REG_VIN_MAX(nr),
544 data->in[nr][index]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100545 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 return count;
547}
548
Guenter Roeck929c6a52012-12-19 22:17:00 +0100549static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0);
550static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in,
551 0, 1);
552static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in,
553 0, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Guenter Roeck929c6a52012-12-19 22:17:00 +0100555static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, 0);
556static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in,
557 1, 1);
558static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in,
559 1, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Guenter Roeck929c6a52012-12-19 22:17:00 +0100561static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, 0);
562static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in,
563 2, 1);
564static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in,
565 2, 2);
566
567static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, 0);
568static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in,
569 3, 1);
570static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in,
571 3, 2);
572
573static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, 0);
574static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in,
575 4, 1);
576static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in,
577 4, 2);
578
579static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, 0);
580static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in,
581 5, 1);
582static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in,
583 5, 2);
584
585static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 6, 0);
586static SENSOR_DEVICE_ATTR_2(in6_min, S_IRUGO | S_IWUSR, show_in, set_in,
587 6, 1);
588static SENSOR_DEVICE_ATTR_2(in6_max, S_IRUGO | S_IWUSR, show_in, set_in,
589 6, 2);
590
591static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 7, 0);
592static SENSOR_DEVICE_ATTR_2(in7_min, S_IRUGO | S_IWUSR, show_in, set_in,
593 7, 1);
594static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in,
595 7, 2);
596
597static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100598static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600/* 3 temperatures */
Jean Delvare20ad93d2005-06-05 11:53:25 +0200601static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
Guenter Roeck60ca3852012-12-19 22:17:00 +0100602 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Guenter Roeck60ca3852012-12-19 22:17:00 +0100604 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
605 int nr = sattr->nr;
606 int index = sattr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 struct it87_data *data = it87_update_device(dev);
Jean Delvare20ad93d2005-06-05 11:53:25 +0200608
Guenter Roeck60ca3852012-12-19 22:17:00 +0100609 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
Jean Delvare20ad93d2005-06-05 11:53:25 +0200611
Guenter Roeck60ca3852012-12-19 22:17:00 +0100612static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
613 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614{
Guenter Roeck60ca3852012-12-19 22:17:00 +0100615 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
616 int nr = sattr->nr;
617 int index = sattr->index;
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200618 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100619 long val;
Guenter Roeck161d8982012-12-19 22:17:01 +0100620 u8 reg, regval;
Jean Delvaref5f64502010-03-05 22:17:19 +0100621
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100622 if (kstrtol(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +0100623 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100625 mutex_lock(&data->update_lock);
Guenter Roeck161d8982012-12-19 22:17:01 +0100626
627 switch (index) {
628 default:
629 case 1:
630 reg = IT87_REG_TEMP_LOW(nr);
631 break;
632 case 2:
633 reg = IT87_REG_TEMP_HIGH(nr);
634 break;
635 case 3:
636 regval = it87_read_value(data, IT87_REG_BEEP_ENABLE);
637 if (!(regval & 0x80)) {
638 regval |= 0x80;
639 it87_write_value(data, IT87_REG_BEEP_ENABLE, regval);
640 }
641 data->valid = 0;
642 reg = IT87_REG_TEMP_OFFSET[nr];
643 break;
644 }
645
Guenter Roeck60ca3852012-12-19 22:17:00 +0100646 data->temp[nr][index] = TEMP_TO_REG(val);
Guenter Roeck161d8982012-12-19 22:17:01 +0100647 it87_write_value(data, reg, data->temp[nr][index]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100648 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 return count;
650}
Jean Delvare20ad93d2005-06-05 11:53:25 +0200651
Guenter Roeck60ca3852012-12-19 22:17:00 +0100652static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
653static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
654 0, 1);
655static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
656 0, 2);
Guenter Roeck161d8982012-12-19 22:17:01 +0100657static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
658 set_temp, 0, 3);
Guenter Roeck60ca3852012-12-19 22:17:00 +0100659static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0);
660static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
661 1, 1);
662static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
663 1, 2);
Guenter Roeck161d8982012-12-19 22:17:01 +0100664static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
665 set_temp, 1, 3);
Guenter Roeck60ca3852012-12-19 22:17:00 +0100666static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0);
667static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
668 2, 1);
669static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
670 2, 2);
Guenter Roeck161d8982012-12-19 22:17:01 +0100671static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
672 set_temp, 2, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Guenter Roeck2cece012012-12-19 22:17:01 +0100674static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
675 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200677 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
678 int nr = sensor_attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 struct it87_data *data = it87_update_device(dev);
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800680 u8 reg = data->sensor; /* In case value is updated while used */
Guenter Roeck19529782012-12-19 22:17:02 +0100681 u8 extra = data->extra;
Jean Delvare5f2dc792010-03-05 22:17:18 +0100682
Guenter Roeck19529782012-12-19 22:17:02 +0100683 if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1))
684 || (has_temp_old_peci(data, nr) && (extra & 0x80)))
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100685 return sprintf(buf, "6\n"); /* Intel PECI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 if (reg & (1 << nr))
687 return sprintf(buf, "3\n"); /* thermal diode */
688 if (reg & (8 << nr))
Jean Delvare4ed10772008-10-17 17:51:16 +0200689 return sprintf(buf, "4\n"); /* thermistor */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return sprintf(buf, "0\n"); /* disabled */
691}
Guenter Roeck2cece012012-12-19 22:17:01 +0100692
693static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
694 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200696 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
697 int nr = sensor_attr->index;
698
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200699 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100700 long val;
Guenter Roeck19529782012-12-19 22:17:02 +0100701 u8 reg, extra;
Jean Delvaref5f64502010-03-05 22:17:19 +0100702
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100703 if (kstrtol(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +0100704 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Jean Delvare8acf07c2010-04-14 16:14:09 +0200706 reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
707 reg &= ~(1 << nr);
708 reg &= ~(8 << nr);
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100709 if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1 || val == 6))
710 reg &= 0x3f;
Guenter Roeck19529782012-12-19 22:17:02 +0100711 extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
712 if (has_temp_old_peci(data, nr) && ((extra & 0x80) || val == 6))
713 extra &= 0x7f;
Jean Delvare4ed10772008-10-17 17:51:16 +0200714 if (val == 2) { /* backwards compatibility */
Guenter Roeck1d9bcf62012-12-19 22:17:01 +0100715 dev_warn(dev,
716 "Sensor type 2 is deprecated, please use 4 instead\n");
Jean Delvare4ed10772008-10-17 17:51:16 +0200717 val = 4;
718 }
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100719 /* 3 = thermal diode; 4 = thermistor; 6 = Intel PECI; 0 = disabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 if (val == 3)
Jean Delvare8acf07c2010-04-14 16:14:09 +0200721 reg |= 1 << nr;
Jean Delvare4ed10772008-10-17 17:51:16 +0200722 else if (val == 4)
Jean Delvare8acf07c2010-04-14 16:14:09 +0200723 reg |= 8 << nr;
Guenter Roeck5d8d2f22012-12-19 22:17:02 +0100724 else if (has_temp_peci(data, nr) && val == 6)
725 reg |= (nr + 1) << 6;
Guenter Roeck19529782012-12-19 22:17:02 +0100726 else if (has_temp_old_peci(data, nr) && val == 6)
727 extra |= 0x80;
Jean Delvare8acf07c2010-04-14 16:14:09 +0200728 else if (val != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 return -EINVAL;
Jean Delvare8acf07c2010-04-14 16:14:09 +0200730
731 mutex_lock(&data->update_lock);
732 data->sensor = reg;
Guenter Roeck19529782012-12-19 22:17:02 +0100733 data->extra = extra;
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200734 it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor);
Guenter Roeck19529782012-12-19 22:17:02 +0100735 if (has_temp_old_peci(data, nr))
736 it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra);
Jean Delvare2b3d1d82010-04-14 16:14:10 +0200737 data->valid = 0; /* Force cache refresh */
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100738 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 return count;
740}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Guenter Roeck2cece012012-12-19 22:17:01 +0100742static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
743 set_temp_type, 0);
744static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
745 set_temp_type, 1);
746static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
747 set_temp_type, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749/* 3 Fans */
Jean Delvareb99883d2010-03-05 22:17:15 +0100750
751static int pwm_mode(const struct it87_data *data, int nr)
752{
753 int ctrl = data->fan_main_ctrl & (1 << nr);
754
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100755 if (ctrl == 0 && data->type != it8603) /* Full speed */
Jean Delvareb99883d2010-03-05 22:17:15 +0100756 return 0;
757 if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
758 return 2;
759 else /* Manual mode */
760 return 1;
761}
762
Jean Delvare20ad93d2005-06-05 11:53:25 +0200763static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
Guenter Roecke1169ba2012-12-19 22:17:01 +0100764 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
Guenter Roecke1169ba2012-12-19 22:17:01 +0100766 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
767 int nr = sattr->nr;
768 int index = sattr->index;
769 int speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 struct it87_data *data = it87_update_device(dev);
Jean Delvare20ad93d2005-06-05 11:53:25 +0200771
Guenter Roecke1169ba2012-12-19 22:17:01 +0100772 speed = has_16bit_fans(data) ?
773 FAN16_FROM_REG(data->fan[nr][index]) :
774 FAN_FROM_REG(data->fan[nr][index],
775 DIV_FROM_REG(data->fan_div[nr]));
776 return sprintf(buf, "%d\n", speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777}
Guenter Roecke1169ba2012-12-19 22:17:01 +0100778
Jean Delvare20ad93d2005-06-05 11:53:25 +0200779static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
780 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200782 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
783 int nr = sensor_attr->index;
784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 struct it87_data *data = it87_update_device(dev);
786 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
787}
Jean Delvare5f2dc792010-03-05 22:17:18 +0100788static ssize_t show_pwm_enable(struct device *dev,
789 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200791 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
792 int nr = sensor_attr->index;
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 struct it87_data *data = it87_update_device(dev);
Jean Delvareb99883d2010-03-05 22:17:15 +0100795 return sprintf(buf, "%d\n", pwm_mode(data, nr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796}
Jean Delvare20ad93d2005-06-05 11:53:25 +0200797static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
798 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200800 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
801 int nr = sensor_attr->index;
802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 struct it87_data *data = it87_update_device(dev);
Jean Delvare44c1bcd2010-10-28 20:31:51 +0200804 return sprintf(buf, "%d\n",
805 pwm_from_reg(data, data->pwm_duty[nr]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
Jean Delvaref8d0c192007-02-14 21:15:02 +0100807static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
808 char *buf)
809{
810 struct it87_data *data = it87_update_device(dev);
811 int index = (data->fan_ctl >> 4) & 0x07;
812
813 return sprintf(buf, "%u\n", pwm_freq[index]);
814}
Guenter Roecke1169ba2012-12-19 22:17:01 +0100815
816static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
817 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818{
Guenter Roecke1169ba2012-12-19 22:17:01 +0100819 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
820 int nr = sattr->nr;
821 int index = sattr->index;
Jean Delvare20ad93d2005-06-05 11:53:25 +0200822
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200823 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100824 long val;
Jean Delvare7f999aa2007-02-14 21:15:03 +0100825 u8 reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100827 if (kstrtol(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +0100828 return -EINVAL;
829
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100830 mutex_lock(&data->update_lock);
Guenter Roecke1169ba2012-12-19 22:17:01 +0100831
832 if (has_16bit_fans(data)) {
833 data->fan[nr][index] = FAN16_TO_REG(val);
834 it87_write_value(data, IT87_REG_FAN_MIN[nr],
835 data->fan[nr][index] & 0xff);
836 it87_write_value(data, IT87_REG_FANX_MIN[nr],
837 data->fan[nr][index] >> 8);
838 } else {
839 reg = it87_read_value(data, IT87_REG_FAN_DIV);
840 switch (nr) {
841 case 0:
842 data->fan_div[nr] = reg & 0x07;
843 break;
844 case 1:
845 data->fan_div[nr] = (reg >> 3) & 0x07;
846 break;
847 case 2:
848 data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
849 break;
850 }
851 data->fan[nr][index] =
852 FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
853 it87_write_value(data, IT87_REG_FAN_MIN[nr],
854 data->fan[nr][index]);
Jean Delvare07eab462005-11-23 15:44:31 -0800855 }
856
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100857 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return count;
859}
Guenter Roecke1169ba2012-12-19 22:17:01 +0100860
Jean Delvare20ad93d2005-06-05 11:53:25 +0200861static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
862 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200864 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
865 int nr = sensor_attr->index;
866
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200867 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100868 unsigned long val;
Jean Delvare8ab4ec32006-08-28 14:35:46 +0200869 int min;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 u8 old;
871
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100872 if (kstrtoul(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +0100873 return -EINVAL;
874
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100875 mutex_lock(&data->update_lock);
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200876 old = it87_read_value(data, IT87_REG_FAN_DIV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
Jean Delvare8ab4ec32006-08-28 14:35:46 +0200878 /* Save fan min limit */
Guenter Roecke1169ba2012-12-19 22:17:01 +0100879 min = FAN_FROM_REG(data->fan[nr][1], DIV_FROM_REG(data->fan_div[nr]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 switch (nr) {
882 case 0:
883 case 1:
884 data->fan_div[nr] = DIV_TO_REG(val);
885 break;
886 case 2:
887 if (val < 8)
888 data->fan_div[nr] = 1;
889 else
890 data->fan_div[nr] = 3;
891 }
892 val = old & 0x80;
893 val |= (data->fan_div[0] & 0x07);
894 val |= (data->fan_div[1] & 0x07) << 3;
895 if (data->fan_div[2] == 3)
896 val |= 0x1 << 6;
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200897 it87_write_value(data, IT87_REG_FAN_DIV, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
Jean Delvare8ab4ec32006-08-28 14:35:46 +0200899 /* Restore fan min limit */
Guenter Roecke1169ba2012-12-19 22:17:01 +0100900 data->fan[nr][1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
901 it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan[nr][1]);
Jean Delvare8ab4ec32006-08-28 14:35:46 +0200902
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100903 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return count;
905}
Jean Delvarecccfc9c2010-03-05 22:17:21 +0100906
907/* Returns 0 if OK, -EINVAL otherwise */
908static int check_trip_points(struct device *dev, int nr)
909{
910 const struct it87_data *data = dev_get_drvdata(dev);
911 int i, err = 0;
912
913 if (has_old_autopwm(data)) {
914 for (i = 0; i < 3; i++) {
915 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
916 err = -EINVAL;
917 }
918 for (i = 0; i < 2; i++) {
919 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
920 err = -EINVAL;
921 }
922 }
923
924 if (err) {
Guenter Roeck1d9bcf62012-12-19 22:17:01 +0100925 dev_err(dev,
926 "Inconsistent trip points, not switching to automatic mode\n");
Jean Delvarecccfc9c2010-03-05 22:17:21 +0100927 dev_err(dev, "Adjust the trip points and try again\n");
928 }
929 return err;
930}
931
Jean Delvare20ad93d2005-06-05 11:53:25 +0200932static ssize_t set_pwm_enable(struct device *dev,
933 struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200935 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
936 int nr = sensor_attr->index;
937
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200938 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100939 long val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100941 if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2)
Jean Delvareb99883d2010-03-05 22:17:15 +0100942 return -EINVAL;
943
Jean Delvarecccfc9c2010-03-05 22:17:21 +0100944 /* Check trip points before switching to automatic mode */
945 if (val == 2) {
946 if (check_trip_points(dev, nr) < 0)
947 return -EINVAL;
948 }
949
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100950 /* IT8603E does not have on/off mode */
951 if (val == 0 && data->type == it8603)
952 return -EINVAL;
953
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100954 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 if (val == 0) {
957 int tmp;
958 /* make sure the fan is on when in on/off mode */
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200959 tmp = it87_read_value(data, IT87_REG_FAN_CTL);
960 it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 /* set on/off mode */
962 data->fan_main_ctrl &= ~(1 << nr);
Jean Delvare5f2dc792010-03-05 22:17:18 +0100963 it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
964 data->fan_main_ctrl);
Jean Delvareb99883d2010-03-05 22:17:15 +0100965 } else {
966 if (val == 1) /* Manual mode */
Jean Delvare16b5dda2012-01-16 22:51:48 +0100967 data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
Jean Delvare6229cdb2010-12-08 16:27:22 +0100968 data->pwm_temp_map[nr] :
969 data->pwm_duty[nr];
Jean Delvareb99883d2010-03-05 22:17:15 +0100970 else /* Automatic mode */
971 data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
972 it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
Rudolf Marekc145d5c2014-01-29 20:40:08 +0100973
974 if (data->type != it8603) {
975 /* set SmartGuardian mode */
976 data->fan_main_ctrl |= (1 << nr);
977 it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
978 data->fan_main_ctrl);
979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 }
981
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100982 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 return count;
984}
Jean Delvare20ad93d2005-06-05 11:53:25 +0200985static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
986 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
Jean Delvare20ad93d2005-06-05 11:53:25 +0200988 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
989 int nr = sensor_attr->index;
990
corentin.labbeb74f3fd2007-06-13 20:27:36 +0200991 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +0100992 long val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100994 if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 return -EINVAL;
996
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100997 mutex_lock(&data->update_lock);
Jean Delvare16b5dda2012-01-16 22:51:48 +0100998 if (has_newer_autopwm(data)) {
Guenter Roeck4a0d71c2012-01-19 11:02:18 -0800999 /*
1000 * If we are in automatic mode, the PWM duty cycle register
1001 * is read-only so we can't write the value.
1002 */
Jean Delvare6229cdb2010-12-08 16:27:22 +01001003 if (data->pwm_ctrl[nr] & 0x80) {
1004 mutex_unlock(&data->update_lock);
1005 return -EBUSY;
1006 }
1007 data->pwm_duty[nr] = pwm_to_reg(data, val);
1008 it87_write_value(data, IT87_REG_PWM_DUTY(nr),
1009 data->pwm_duty[nr]);
1010 } else {
1011 data->pwm_duty[nr] = pwm_to_reg(data, val);
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08001012 /*
1013 * If we are in manual mode, write the duty cycle immediately;
1014 * otherwise, just store it for later use.
1015 */
Jean Delvare6229cdb2010-12-08 16:27:22 +01001016 if (!(data->pwm_ctrl[nr] & 0x80)) {
1017 data->pwm_ctrl[nr] = data->pwm_duty[nr];
1018 it87_write_value(data, IT87_REG_PWM(nr),
1019 data->pwm_ctrl[nr]);
1020 }
Jean Delvareb99883d2010-03-05 22:17:15 +01001021 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001022 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 return count;
1024}
Jean Delvaref8d0c192007-02-14 21:15:02 +01001025static ssize_t set_pwm_freq(struct device *dev,
1026 struct device_attribute *attr, const char *buf, size_t count)
1027{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001028 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +01001029 unsigned long val;
Jean Delvaref8d0c192007-02-14 21:15:02 +01001030 int i;
1031
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001032 if (kstrtoul(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +01001033 return -EINVAL;
1034
Jean Delvaref8d0c192007-02-14 21:15:02 +01001035 /* Search for the nearest available frequency */
1036 for (i = 0; i < 7; i++) {
1037 if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
1038 break;
1039 }
1040
1041 mutex_lock(&data->update_lock);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001042 data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f;
Jean Delvaref8d0c192007-02-14 21:15:02 +01001043 data->fan_ctl |= i << 4;
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001044 it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl);
Jean Delvaref8d0c192007-02-14 21:15:02 +01001045 mutex_unlock(&data->update_lock);
1046
1047 return count;
1048}
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001049static ssize_t show_pwm_temp_map(struct device *dev,
1050 struct device_attribute *attr, char *buf)
1051{
1052 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1053 int nr = sensor_attr->index;
1054
1055 struct it87_data *data = it87_update_device(dev);
1056 int map;
1057
1058 if (data->pwm_temp_map[nr] < 3)
1059 map = 1 << data->pwm_temp_map[nr];
1060 else
1061 map = 0; /* Should never happen */
1062 return sprintf(buf, "%d\n", map);
1063}
1064static ssize_t set_pwm_temp_map(struct device *dev,
1065 struct device_attribute *attr, const char *buf, size_t count)
1066{
1067 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1068 int nr = sensor_attr->index;
1069
1070 struct it87_data *data = dev_get_drvdata(dev);
1071 long val;
1072 u8 reg;
1073
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08001074 /*
1075 * This check can go away if we ever support automatic fan speed
1076 * control on newer chips.
1077 */
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001078 if (!has_old_autopwm(data)) {
1079 dev_notice(dev, "Mapping change disabled for safety reasons\n");
1080 return -EINVAL;
1081 }
1082
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001083 if (kstrtol(buf, 10, &val) < 0)
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001084 return -EINVAL;
1085
1086 switch (val) {
1087 case (1 << 0):
1088 reg = 0x00;
1089 break;
1090 case (1 << 1):
1091 reg = 0x01;
1092 break;
1093 case (1 << 2):
1094 reg = 0x02;
1095 break;
1096 default:
1097 return -EINVAL;
1098 }
1099
1100 mutex_lock(&data->update_lock);
1101 data->pwm_temp_map[nr] = reg;
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08001102 /*
1103 * If we are in automatic mode, write the temp mapping immediately;
1104 * otherwise, just store it for later use.
1105 */
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001106 if (data->pwm_ctrl[nr] & 0x80) {
1107 data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
1108 it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
1109 }
1110 mutex_unlock(&data->update_lock);
1111 return count;
1112}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001114static ssize_t show_auto_pwm(struct device *dev,
1115 struct device_attribute *attr, char *buf)
1116{
1117 struct it87_data *data = it87_update_device(dev);
1118 struct sensor_device_attribute_2 *sensor_attr =
1119 to_sensor_dev_attr_2(attr);
1120 int nr = sensor_attr->nr;
1121 int point = sensor_attr->index;
1122
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001123 return sprintf(buf, "%d\n",
1124 pwm_from_reg(data, data->auto_pwm[nr][point]));
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001125}
1126
1127static ssize_t set_auto_pwm(struct device *dev,
1128 struct device_attribute *attr, const char *buf, size_t count)
1129{
1130 struct it87_data *data = dev_get_drvdata(dev);
1131 struct sensor_device_attribute_2 *sensor_attr =
1132 to_sensor_dev_attr_2(attr);
1133 int nr = sensor_attr->nr;
1134 int point = sensor_attr->index;
1135 long val;
1136
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001137 if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001138 return -EINVAL;
1139
1140 mutex_lock(&data->update_lock);
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001141 data->auto_pwm[nr][point] = pwm_to_reg(data, val);
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001142 it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
1143 data->auto_pwm[nr][point]);
1144 mutex_unlock(&data->update_lock);
1145 return count;
1146}
1147
1148static ssize_t show_auto_temp(struct device *dev,
1149 struct device_attribute *attr, char *buf)
1150{
1151 struct it87_data *data = it87_update_device(dev);
1152 struct sensor_device_attribute_2 *sensor_attr =
1153 to_sensor_dev_attr_2(attr);
1154 int nr = sensor_attr->nr;
1155 int point = sensor_attr->index;
1156
1157 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point]));
1158}
1159
1160static ssize_t set_auto_temp(struct device *dev,
1161 struct device_attribute *attr, const char *buf, size_t count)
1162{
1163 struct it87_data *data = dev_get_drvdata(dev);
1164 struct sensor_device_attribute_2 *sensor_attr =
1165 to_sensor_dev_attr_2(attr);
1166 int nr = sensor_attr->nr;
1167 int point = sensor_attr->index;
1168 long val;
1169
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001170 if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001171 return -EINVAL;
1172
1173 mutex_lock(&data->update_lock);
1174 data->auto_temp[nr][point] = TEMP_TO_REG(val);
1175 it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
1176 data->auto_temp[nr][point]);
1177 mutex_unlock(&data->update_lock);
1178 return count;
1179}
1180
Guenter Roecke1169ba2012-12-19 22:17:01 +01001181static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0);
1182static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
1183 0, 1);
1184static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div,
1185 set_fan_div, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
Guenter Roecke1169ba2012-12-19 22:17:01 +01001187static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, 0);
1188static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
1189 1, 1);
1190static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, show_fan_div,
1191 set_fan_div, 1);
1192
1193static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, 0);
1194static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
1195 2, 1);
1196static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, show_fan_div,
1197 set_fan_div, 2);
1198
1199static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, 0);
1200static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
1201 3, 1);
1202
1203static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, 0);
1204static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
1205 4, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Guenter Roeckc4458db2012-12-19 22:17:02 +01001207static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
1208 show_pwm_enable, set_pwm_enable, 0);
1209static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
1210static DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq);
1211static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR,
1212 show_pwm_temp_map, set_pwm_temp_map, 0);
1213static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR,
1214 show_auto_pwm, set_auto_pwm, 0, 0);
1215static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR,
1216 show_auto_pwm, set_auto_pwm, 0, 1);
1217static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR,
1218 show_auto_pwm, set_auto_pwm, 0, 2);
1219static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO,
1220 show_auto_pwm, NULL, 0, 3);
1221static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
1222 show_auto_temp, set_auto_temp, 0, 1);
1223static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
1224 show_auto_temp, set_auto_temp, 0, 0);
1225static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
1226 show_auto_temp, set_auto_temp, 0, 2);
1227static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
1228 show_auto_temp, set_auto_temp, 0, 3);
1229static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR,
1230 show_auto_temp, set_auto_temp, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Guenter Roeckc4458db2012-12-19 22:17:02 +01001232static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
1233 show_pwm_enable, set_pwm_enable, 1);
1234static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
1235static DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, NULL);
1236static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR,
1237 show_pwm_temp_map, set_pwm_temp_map, 1);
1238static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR,
1239 show_auto_pwm, set_auto_pwm, 1, 0);
1240static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR,
1241 show_auto_pwm, set_auto_pwm, 1, 1);
1242static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO | S_IWUSR,
1243 show_auto_pwm, set_auto_pwm, 1, 2);
1244static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO,
1245 show_auto_pwm, NULL, 1, 3);
1246static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
1247 show_auto_temp, set_auto_temp, 1, 1);
1248static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
1249 show_auto_temp, set_auto_temp, 1, 0);
1250static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
1251 show_auto_temp, set_auto_temp, 1, 2);
1252static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
1253 show_auto_temp, set_auto_temp, 1, 3);
1254static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR,
1255 show_auto_temp, set_auto_temp, 1, 4);
1256
1257static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
1258 show_pwm_enable, set_pwm_enable, 2);
1259static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2);
1260static DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL);
1261static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR,
1262 show_pwm_temp_map, set_pwm_temp_map, 2);
1263static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR,
1264 show_auto_pwm, set_auto_pwm, 2, 0);
1265static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR,
1266 show_auto_pwm, set_auto_pwm, 2, 1);
1267static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO | S_IWUSR,
1268 show_auto_pwm, set_auto_pwm, 2, 2);
1269static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO,
1270 show_auto_pwm, NULL, 2, 3);
1271static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
1272 show_auto_temp, set_auto_temp, 2, 1);
1273static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
1274 show_auto_temp, set_auto_temp, 2, 0);
1275static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
1276 show_auto_temp, set_auto_temp, 2, 2);
1277static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
1278 show_auto_temp, set_auto_temp, 2, 3);
1279static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR,
1280 show_auto_temp, set_auto_temp, 2, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282/* Alarms */
Jean Delvare5f2dc792010-03-05 22:17:18 +01001283static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
1284 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285{
1286 struct it87_data *data = it87_update_device(dev);
Jean Delvare68188ba2005-05-16 18:52:38 +02001287 return sprintf(buf, "%u\n", data->alarms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288}
Jean Delvare1d66c642005-04-18 21:16:59 -07001289static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Jean Delvare0124dd72007-11-25 16:16:41 +01001291static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
1292 char *buf)
1293{
1294 int bitnr = to_sensor_dev_attr(attr)->index;
1295 struct it87_data *data = it87_update_device(dev);
1296 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
1297}
Jean Delvare3d30f9e2011-07-25 21:46:10 +02001298
1299static ssize_t clear_intrusion(struct device *dev, struct device_attribute
1300 *attr, const char *buf, size_t count)
1301{
1302 struct it87_data *data = dev_get_drvdata(dev);
1303 long val;
1304 int config;
1305
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001306 if (kstrtol(buf, 10, &val) < 0 || val != 0)
Jean Delvare3d30f9e2011-07-25 21:46:10 +02001307 return -EINVAL;
1308
1309 mutex_lock(&data->update_lock);
1310 config = it87_read_value(data, IT87_REG_CONFIG);
1311 if (config < 0) {
1312 count = config;
1313 } else {
1314 config |= 1 << 5;
1315 it87_write_value(data, IT87_REG_CONFIG, config);
1316 /* Invalidate cache to force re-read */
1317 data->valid = 0;
1318 }
1319 mutex_unlock(&data->update_lock);
1320
1321 return count;
1322}
1323
Jean Delvare0124dd72007-11-25 16:16:41 +01001324static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
1325static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
1326static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
1327static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
1328static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
1329static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
1330static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
1331static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
1332static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
1333static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1);
1334static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2);
1335static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3);
1336static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
1337static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
1338static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
1339static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
Jean Delvare3d30f9e2011-07-25 21:46:10 +02001340static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
1341 show_alarm, clear_intrusion, 4);
Jean Delvare0124dd72007-11-25 16:16:41 +01001342
Jean Delvared9b327c2010-03-05 22:17:17 +01001343static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
1344 char *buf)
1345{
1346 int bitnr = to_sensor_dev_attr(attr)->index;
1347 struct it87_data *data = it87_update_device(dev);
1348 return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1);
1349}
1350static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
1351 const char *buf, size_t count)
1352{
1353 int bitnr = to_sensor_dev_attr(attr)->index;
1354 struct it87_data *data = dev_get_drvdata(dev);
1355 long val;
1356
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001357 if (kstrtol(buf, 10, &val) < 0
Jean Delvared9b327c2010-03-05 22:17:17 +01001358 || (val != 0 && val != 1))
1359 return -EINVAL;
1360
1361 mutex_lock(&data->update_lock);
1362 data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
1363 if (val)
1364 data->beeps |= (1 << bitnr);
1365 else
1366 data->beeps &= ~(1 << bitnr);
1367 it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps);
1368 mutex_unlock(&data->update_lock);
1369 return count;
1370}
1371
1372static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
1373 show_beep, set_beep, 1);
1374static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1);
1375static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1);
1376static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1);
1377static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1);
1378static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1);
1379static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1);
1380static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1);
1381/* fanX_beep writability is set later */
1382static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0);
1383static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0);
1384static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0);
1385static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0);
1386static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0);
1387static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
1388 show_beep, set_beep, 2);
1389static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2);
1390static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2);
1391
Jean Delvare5f2dc792010-03-05 22:17:18 +01001392static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
1393 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
Jean Delvare90d66192007-10-08 18:24:35 +02001395 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvarea7be58a2005-12-18 16:40:14 +01001396 return sprintf(buf, "%u\n", data->vrm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397}
Jean Delvare5f2dc792010-03-05 22:17:18 +01001398static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
1399 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001401 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvaref5f64502010-03-05 22:17:19 +01001402 unsigned long val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001404 if (kstrtoul(buf, 10, &val) < 0)
Jean Delvaref5f64502010-03-05 22:17:19 +01001405 return -EINVAL;
1406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 data->vrm = val;
1408
1409 return count;
1410}
1411static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Jean Delvare5f2dc792010-03-05 22:17:18 +01001413static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
1414 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415{
1416 struct it87_data *data = it87_update_device(dev);
1417 return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
1418}
1419static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
Jean Delvare87808be2006-09-24 21:17:13 +02001420
Jean Delvare738e5e02010-08-14 21:08:50 +02001421static ssize_t show_label(struct device *dev, struct device_attribute *attr,
1422 char *buf)
1423{
Guenter Roeck3c4c4972012-01-20 09:29:44 -08001424 static const char * const labels[] = {
Jean Delvare738e5e02010-08-14 21:08:50 +02001425 "+5V",
1426 "5VSB",
1427 "Vbat",
1428 };
Guenter Roeck3c4c4972012-01-20 09:29:44 -08001429 static const char * const labels_it8721[] = {
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001430 "+3.3V",
1431 "3VSB",
1432 "Vbat",
1433 };
1434 struct it87_data *data = dev_get_drvdata(dev);
Jean Delvare738e5e02010-08-14 21:08:50 +02001435 int nr = to_sensor_dev_attr(attr)->index;
1436
Jean Delvare16b5dda2012-01-16 22:51:48 +01001437 return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
1438 : labels[nr]);
Jean Delvare738e5e02010-08-14 21:08:50 +02001439}
1440static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
1441static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
1442static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
Rudolf Marek7183ae82014-04-04 18:01:35 +02001443/* special AVCC3 IT8603E in9 */
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001444static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
Jean Delvare738e5e02010-08-14 21:08:50 +02001445
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001446static ssize_t show_name(struct device *dev, struct device_attribute
1447 *devattr, char *buf)
1448{
1449 struct it87_data *data = dev_get_drvdata(dev);
1450 return sprintf(buf, "%s\n", data->name);
1451}
1452static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1453
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001454static struct attribute *it87_attributes_in[10][5] = {
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001455{
Jean Delvare87808be2006-09-24 21:17:13 +02001456 &sensor_dev_attr_in0_input.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001457 &sensor_dev_attr_in0_min.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001458 &sensor_dev_attr_in0_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001459 &sensor_dev_attr_in0_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001460 NULL
1461}, {
1462 &sensor_dev_attr_in1_input.dev_attr.attr,
1463 &sensor_dev_attr_in1_min.dev_attr.attr,
1464 &sensor_dev_attr_in1_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001465 &sensor_dev_attr_in1_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001466 NULL
1467}, {
1468 &sensor_dev_attr_in2_input.dev_attr.attr,
1469 &sensor_dev_attr_in2_min.dev_attr.attr,
1470 &sensor_dev_attr_in2_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001471 &sensor_dev_attr_in2_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001472 NULL
1473}, {
1474 &sensor_dev_attr_in3_input.dev_attr.attr,
1475 &sensor_dev_attr_in3_min.dev_attr.attr,
1476 &sensor_dev_attr_in3_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001477 &sensor_dev_attr_in3_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001478 NULL
1479}, {
1480 &sensor_dev_attr_in4_input.dev_attr.attr,
1481 &sensor_dev_attr_in4_min.dev_attr.attr,
1482 &sensor_dev_attr_in4_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001483 &sensor_dev_attr_in4_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001484 NULL
1485}, {
1486 &sensor_dev_attr_in5_input.dev_attr.attr,
1487 &sensor_dev_attr_in5_min.dev_attr.attr,
1488 &sensor_dev_attr_in5_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001489 &sensor_dev_attr_in5_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001490 NULL
1491}, {
1492 &sensor_dev_attr_in6_input.dev_attr.attr,
1493 &sensor_dev_attr_in6_min.dev_attr.attr,
1494 &sensor_dev_attr_in6_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001495 &sensor_dev_attr_in6_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001496 NULL
1497}, {
1498 &sensor_dev_attr_in7_input.dev_attr.attr,
1499 &sensor_dev_attr_in7_min.dev_attr.attr,
1500 &sensor_dev_attr_in7_max.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001501 &sensor_dev_attr_in7_alarm.dev_attr.attr,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001502 NULL
1503}, {
1504 &sensor_dev_attr_in8_input.dev_attr.attr,
1505 NULL
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001506}, {
1507 &sensor_dev_attr_in9_input.dev_attr.attr,
1508 NULL
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001509} };
Jean Delvare87808be2006-09-24 21:17:13 +02001510
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001511static const struct attribute_group it87_group_in[10] = {
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001512 { .attrs = it87_attributes_in[0] },
1513 { .attrs = it87_attributes_in[1] },
1514 { .attrs = it87_attributes_in[2] },
1515 { .attrs = it87_attributes_in[3] },
1516 { .attrs = it87_attributes_in[4] },
1517 { .attrs = it87_attributes_in[5] },
1518 { .attrs = it87_attributes_in[6] },
1519 { .attrs = it87_attributes_in[7] },
1520 { .attrs = it87_attributes_in[8] },
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001521 { .attrs = it87_attributes_in[9] },
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001522};
1523
Guenter Roeck4573acb2012-03-26 16:17:41 -07001524static struct attribute *it87_attributes_temp[3][6] = {
1525{
Jean Delvare87808be2006-09-24 21:17:13 +02001526 &sensor_dev_attr_temp1_input.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001527 &sensor_dev_attr_temp1_max.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001528 &sensor_dev_attr_temp1_min.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001529 &sensor_dev_attr_temp1_type.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001530 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
Guenter Roeck4573acb2012-03-26 16:17:41 -07001531 NULL
1532} , {
1533 &sensor_dev_attr_temp2_input.dev_attr.attr,
1534 &sensor_dev_attr_temp2_max.dev_attr.attr,
1535 &sensor_dev_attr_temp2_min.dev_attr.attr,
1536 &sensor_dev_attr_temp2_type.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001537 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
Guenter Roeck4573acb2012-03-26 16:17:41 -07001538 NULL
1539} , {
1540 &sensor_dev_attr_temp3_input.dev_attr.attr,
1541 &sensor_dev_attr_temp3_max.dev_attr.attr,
1542 &sensor_dev_attr_temp3_min.dev_attr.attr,
1543 &sensor_dev_attr_temp3_type.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001544 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
Guenter Roeck4573acb2012-03-26 16:17:41 -07001545 NULL
1546} };
Jean Delvare87808be2006-09-24 21:17:13 +02001547
Guenter Roeck4573acb2012-03-26 16:17:41 -07001548static const struct attribute_group it87_group_temp[3] = {
1549 { .attrs = it87_attributes_temp[0] },
1550 { .attrs = it87_attributes_temp[1] },
1551 { .attrs = it87_attributes_temp[2] },
1552};
1553
Guenter Roeck161d8982012-12-19 22:17:01 +01001554static struct attribute *it87_attributes_temp_offset[] = {
1555 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1556 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1557 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1558};
1559
Guenter Roeck4573acb2012-03-26 16:17:41 -07001560static struct attribute *it87_attributes[] = {
Jean Delvare87808be2006-09-24 21:17:13 +02001561 &dev_attr_alarms.attr,
Jean Delvare3d30f9e2011-07-25 21:46:10 +02001562 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001563 &dev_attr_name.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001564 NULL
1565};
1566
1567static const struct attribute_group it87_group = {
1568 .attrs = it87_attributes,
1569};
1570
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001571static struct attribute *it87_attributes_in_beep[] = {
Jean Delvared9b327c2010-03-05 22:17:17 +01001572 &sensor_dev_attr_in0_beep.dev_attr.attr,
1573 &sensor_dev_attr_in1_beep.dev_attr.attr,
1574 &sensor_dev_attr_in2_beep.dev_attr.attr,
1575 &sensor_dev_attr_in3_beep.dev_attr.attr,
1576 &sensor_dev_attr_in4_beep.dev_attr.attr,
1577 &sensor_dev_attr_in5_beep.dev_attr.attr,
1578 &sensor_dev_attr_in6_beep.dev_attr.attr,
1579 &sensor_dev_attr_in7_beep.dev_attr.attr,
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001580 NULL,
1581 NULL,
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001582};
Jean Delvared9b327c2010-03-05 22:17:17 +01001583
Guenter Roeck4573acb2012-03-26 16:17:41 -07001584static struct attribute *it87_attributes_temp_beep[] = {
Jean Delvared9b327c2010-03-05 22:17:17 +01001585 &sensor_dev_attr_temp1_beep.dev_attr.attr,
1586 &sensor_dev_attr_temp2_beep.dev_attr.attr,
1587 &sensor_dev_attr_temp3_beep.dev_attr.attr,
Jean Delvared9b327c2010-03-05 22:17:17 +01001588};
1589
Guenter Roecke1169ba2012-12-19 22:17:01 +01001590static struct attribute *it87_attributes_fan[5][3+1] = { {
Jean Delvare87808be2006-09-24 21:17:13 +02001591 &sensor_dev_attr_fan1_input.dev_attr.attr,
1592 &sensor_dev_attr_fan1_min.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001593 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
1594 NULL
1595}, {
Jean Delvare87808be2006-09-24 21:17:13 +02001596 &sensor_dev_attr_fan2_input.dev_attr.attr,
1597 &sensor_dev_attr_fan2_min.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001598 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
1599 NULL
1600}, {
Jean Delvare87808be2006-09-24 21:17:13 +02001601 &sensor_dev_attr_fan3_input.dev_attr.attr,
1602 &sensor_dev_attr_fan3_min.dev_attr.attr,
Jean Delvare0124dd72007-11-25 16:16:41 +01001603 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001604 NULL
Guenter Roecke1169ba2012-12-19 22:17:01 +01001605}, {
1606 &sensor_dev_attr_fan4_input.dev_attr.attr,
1607 &sensor_dev_attr_fan4_min.dev_attr.attr,
1608 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
1609 NULL
1610}, {
1611 &sensor_dev_attr_fan5_input.dev_attr.attr,
1612 &sensor_dev_attr_fan5_min.dev_attr.attr,
1613 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
1614 NULL
Jean Delvare723a0aa2010-03-05 22:17:16 +01001615} };
Jean Delvare0124dd72007-11-25 16:16:41 +01001616
Guenter Roecke1169ba2012-12-19 22:17:01 +01001617static const struct attribute_group it87_group_fan[5] = {
Jean Delvare723a0aa2010-03-05 22:17:16 +01001618 { .attrs = it87_attributes_fan[0] },
1619 { .attrs = it87_attributes_fan[1] },
1620 { .attrs = it87_attributes_fan[2] },
Guenter Roecke1169ba2012-12-19 22:17:01 +01001621 { .attrs = it87_attributes_fan[3] },
1622 { .attrs = it87_attributes_fan[4] },
Jean Delvare723a0aa2010-03-05 22:17:16 +01001623};
1624
Guenter Roecke1169ba2012-12-19 22:17:01 +01001625static const struct attribute *it87_attributes_fan_div[] = {
1626 &sensor_dev_attr_fan1_div.dev_attr.attr,
1627 &sensor_dev_attr_fan2_div.dev_attr.attr,
1628 &sensor_dev_attr_fan3_div.dev_attr.attr,
1629};
Jean Delvare723a0aa2010-03-05 22:17:16 +01001630
1631static struct attribute *it87_attributes_pwm[3][4+1] = { {
Jean Delvare87808be2006-09-24 21:17:13 +02001632 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
Jean Delvare87808be2006-09-24 21:17:13 +02001633 &sensor_dev_attr_pwm1.dev_attr.attr,
Jean Delvared5b0b5d2007-12-14 14:41:53 +01001634 &dev_attr_pwm1_freq.attr,
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001635 &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001636 NULL
1637}, {
1638 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1639 &sensor_dev_attr_pwm2.dev_attr.attr,
1640 &dev_attr_pwm2_freq.attr,
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001641 &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001642 NULL
1643}, {
1644 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
1645 &sensor_dev_attr_pwm3.dev_attr.attr,
1646 &dev_attr_pwm3_freq.attr,
Jean Delvare94ac7ee2010-03-05 22:17:16 +01001647 &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
Jean Delvare723a0aa2010-03-05 22:17:16 +01001648 NULL
1649} };
Jean Delvare87808be2006-09-24 21:17:13 +02001650
Jean Delvare723a0aa2010-03-05 22:17:16 +01001651static const struct attribute_group it87_group_pwm[3] = {
1652 { .attrs = it87_attributes_pwm[0] },
1653 { .attrs = it87_attributes_pwm[1] },
1654 { .attrs = it87_attributes_pwm[2] },
1655};
1656
Jean Delvare4f3f51b2010-03-05 22:17:21 +01001657static struct attribute *it87_attributes_autopwm[3][9+1] = { {
1658 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1659 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
1660 &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
1661 &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
1662 &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
1663 &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
1664 &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
1665 &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
1666 &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
1667 NULL
1668}, {
1669 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1670 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1671 &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
1672 &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
1673 &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
1674 &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr,
1675 &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
1676 &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
1677 &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
1678 NULL
1679}, {
1680 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
1681 &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
1682 &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
1683 &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
1684 &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
1685 &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr,
1686 &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
1687 &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
1688 &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
1689 NULL
1690} };
1691
1692static const struct attribute_group it87_group_autopwm[3] = {
1693 { .attrs = it87_attributes_autopwm[0] },
1694 { .attrs = it87_attributes_autopwm[1] },
1695 { .attrs = it87_attributes_autopwm[2] },
1696};
1697
Jean Delvared9b327c2010-03-05 22:17:17 +01001698static struct attribute *it87_attributes_fan_beep[] = {
1699 &sensor_dev_attr_fan1_beep.dev_attr.attr,
1700 &sensor_dev_attr_fan2_beep.dev_attr.attr,
1701 &sensor_dev_attr_fan3_beep.dev_attr.attr,
1702 &sensor_dev_attr_fan4_beep.dev_attr.attr,
1703 &sensor_dev_attr_fan5_beep.dev_attr.attr,
1704};
1705
Jean Delvare6a8d7ac2010-03-05 22:17:16 +01001706static struct attribute *it87_attributes_vid[] = {
Jean Delvare87808be2006-09-24 21:17:13 +02001707 &dev_attr_vrm.attr,
1708 &dev_attr_cpu0_vid.attr,
1709 NULL
1710};
1711
Jean Delvare6a8d7ac2010-03-05 22:17:16 +01001712static const struct attribute_group it87_group_vid = {
1713 .attrs = it87_attributes_vid,
Jean Delvare87808be2006-09-24 21:17:13 +02001714};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
Jean Delvare738e5e02010-08-14 21:08:50 +02001716static struct attribute *it87_attributes_label[] = {
1717 &sensor_dev_attr_in3_label.dev_attr.attr,
1718 &sensor_dev_attr_in7_label.dev_attr.attr,
1719 &sensor_dev_attr_in8_label.dev_attr.attr,
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001720 &sensor_dev_attr_in9_label.dev_attr.attr,
Jean Delvare738e5e02010-08-14 21:08:50 +02001721 NULL
1722};
1723
1724static const struct attribute_group it87_group_label = {
Jean Delvarefa8b6972011-07-17 18:39:19 +02001725 .attrs = it87_attributes_label,
Jean Delvare738e5e02010-08-14 21:08:50 +02001726};
1727
Jean Delvare2d8672c2005-07-19 23:56:35 +02001728/* SuperIO detection - will change isa_address if a chip is found */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001729static int __init it87_find(unsigned short *address,
1730 struct it87_sio_data *sio_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731{
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +02001732 int err;
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001733 u16 chip_type;
Jean Delvare98dd22c2008-10-09 15:33:58 +02001734 const char *board_vendor, *board_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
Nat Gurumoorthy5b0380c2011-05-25 20:43:33 +02001736 err = superio_enter();
1737 if (err)
1738 return err;
1739
1740 err = -ENODEV;
Jean Delvare67b671b2007-12-06 23:13:42 +01001741 chip_type = force_id ? force_id : superio_inw(DEVID);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001742
1743 switch (chip_type) {
1744 case IT8705F_DEVID:
1745 sio_data->type = it87;
1746 break;
1747 case IT8712F_DEVID:
1748 sio_data->type = it8712;
1749 break;
1750 case IT8716F_DEVID:
1751 case IT8726F_DEVID:
1752 sio_data->type = it8716;
1753 break;
1754 case IT8718F_DEVID:
1755 sio_data->type = it8718;
1756 break;
Jean-Marc Spaggiarib4da93e2009-01-07 16:37:32 +01001757 case IT8720F_DEVID:
1758 sio_data->type = it8720;
1759 break;
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001760 case IT8721F_DEVID:
1761 sio_data->type = it8721;
1762 break;
Jean Delvare16b5dda2012-01-16 22:51:48 +01001763 case IT8728F_DEVID:
1764 sio_data->type = it8728;
1765 break;
Guenter Roeckb0636702012-09-07 17:34:41 -06001766 case IT8771E_DEVID:
1767 sio_data->type = it8771;
1768 break;
1769 case IT8772E_DEVID:
1770 sio_data->type = it8772;
1771 break;
Guenter Roeck7bc32d22015-01-17 14:10:24 -08001772 case IT8781F_DEVID:
1773 sio_data->type = it8781;
1774 break;
Guenter Roeck0531d982012-03-02 11:46:44 -08001775 case IT8782F_DEVID:
1776 sio_data->type = it8782;
1777 break;
1778 case IT8783E_DEVID:
1779 sio_data->type = it8783;
1780 break;
Rudolf Marek7183ae82014-04-04 18:01:35 +02001781 case IT8603E_DEVID:
Rudolf Marek574e9bd2014-04-04 18:01:35 +02001782 case IT8623E_DEVID:
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001783 sio_data->type = it8603;
1784 break;
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001785 case 0xffff: /* No device at all */
1786 goto exit;
1787 default:
Joe Perchesa8ca1032011-01-12 21:55:10 +01001788 pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001789 goto exit;
1790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
Jean Delvare87673dd2006-08-28 14:37:19 +02001792 superio_select(PME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01001794 pr_info("Device not activated, skipping\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 goto exit;
1796 }
1797
1798 *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
1799 if (*address == 0) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01001800 pr_info("Base address not set, skipping\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 goto exit;
1802 }
1803
1804 err = 0;
Andrew Paprocki04751692008-08-06 22:41:06 +02001805 sio_data->revision = superio_inb(DEVREV) & 0x0f;
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001806 pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type,
Jean Delvareb523bb72014-01-29 20:40:08 +01001807 chip_type == 0x8771 || chip_type == 0x8772 ||
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001808 chip_type == 0x8603 ? 'E' : 'F', *address,
1809 sio_data->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
Jean Delvare738e5e02010-08-14 21:08:50 +02001811 /* in8 (Vbat) is always internal */
1812 sio_data->internal = (1 << 2);
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001813 /* Only the IT8603E has in9 */
1814 if (sio_data->type != it8603)
1815 sio_data->skip_in |= (1 << 9);
Jean Delvare738e5e02010-08-14 21:08:50 +02001816
Jean Delvare87673dd2006-08-28 14:37:19 +02001817 /* Read GPIO config and VID value from LDN 7 (GPIO) */
Jean Delvare895ff262009-12-09 20:35:47 +01001818 if (sio_data->type == it87) {
1819 /* The IT8705F doesn't have VID pins at all */
1820 sio_data->skip_vid = 1;
Jean Delvared9b327c2010-03-05 22:17:17 +01001821
1822 /* The IT8705F has a different LD number for GPIO */
1823 superio_select(5);
1824 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
Guenter Roeck0531d982012-03-02 11:46:44 -08001825 } else if (sio_data->type == it8783) {
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001826 int reg25, reg27, reg2a, reg2c, regef;
Guenter Roeck0531d982012-03-02 11:46:44 -08001827
1828 sio_data->skip_vid = 1; /* No VID */
1829
1830 superio_select(GPIO);
1831
1832 reg25 = superio_inb(IT87_SIO_GPIO1_REG);
1833 reg27 = superio_inb(IT87_SIO_GPIO3_REG);
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001834 reg2a = superio_inb(IT87_SIO_PINX1_REG);
1835 reg2c = superio_inb(IT87_SIO_PINX2_REG);
1836 regef = superio_inb(IT87_SIO_SPI_REG);
Guenter Roeck0531d982012-03-02 11:46:44 -08001837
Guenter Roeck0531d982012-03-02 11:46:44 -08001838 /* Check if fan3 is there or not */
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001839 if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
Guenter Roeck0531d982012-03-02 11:46:44 -08001840 sio_data->skip_fan |= (1 << 2);
1841 if ((reg25 & (1 << 4))
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001842 || (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
Guenter Roeck0531d982012-03-02 11:46:44 -08001843 sio_data->skip_pwm |= (1 << 2);
1844
1845 /* Check if fan2 is there or not */
1846 if (reg27 & (1 << 7))
1847 sio_data->skip_fan |= (1 << 1);
1848 if (reg27 & (1 << 3))
1849 sio_data->skip_pwm |= (1 << 1);
1850
1851 /* VIN5 */
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001852 if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001853 sio_data->skip_in |= (1 << 5); /* No VIN5 */
Guenter Roeck0531d982012-03-02 11:46:44 -08001854
1855 /* VIN6 */
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001856 if (reg27 & (1 << 1))
1857 sio_data->skip_in |= (1 << 6); /* No VIN6 */
Guenter Roeck0531d982012-03-02 11:46:44 -08001858
1859 /*
1860 * VIN7
1861 * Does not depend on bit 2 of Reg2C, contrary to datasheet.
1862 */
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001863 if (reg27 & (1 << 2)) {
1864 /*
1865 * The data sheet is a bit unclear regarding the
1866 * internal voltage divider for VCCH5V. It says
1867 * "This bit enables and switches VIN7 (pin 91) to the
1868 * internal voltage divider for VCCH5V".
1869 * This is different to other chips, where the internal
1870 * voltage divider would connect VIN7 to an internal
1871 * voltage source. Maybe that is the case here as well.
1872 *
1873 * Since we don't know for sure, re-route it if that is
1874 * not the case, and ask the user to report if the
1875 * resulting voltage is sane.
1876 */
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001877 if (!(reg2c & (1 << 1))) {
1878 reg2c |= (1 << 1);
1879 superio_outb(IT87_SIO_PINX2_REG, reg2c);
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001880 pr_notice("Routing internal VCCH5V to in7.\n");
1881 }
1882 pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
1883 pr_notice("Please report if it displays a reasonable voltage.\n");
1884 }
Guenter Roeck0531d982012-03-02 11:46:44 -08001885
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001886 if (reg2c & (1 << 0))
Guenter Roeck0531d982012-03-02 11:46:44 -08001887 sio_data->internal |= (1 << 0);
Guenter Roeck088ce2a2013-03-13 16:40:39 -07001888 if (reg2c & (1 << 1))
Guenter Roeck0531d982012-03-02 11:46:44 -08001889 sio_data->internal |= (1 << 1);
1890
1891 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001892 } else if (sio_data->type == it8603) {
1893 int reg27, reg29;
Guenter Roeck0531d982012-03-02 11:46:44 -08001894
Rudolf Marekc145d5c2014-01-29 20:40:08 +01001895 sio_data->skip_vid = 1; /* No VID */
1896 superio_select(GPIO);
1897
1898 reg27 = superio_inb(IT87_SIO_GPIO3_REG);
1899
1900 /* Check if fan3 is there or not */
1901 if (reg27 & (1 << 6))
1902 sio_data->skip_pwm |= (1 << 2);
1903 if (reg27 & (1 << 7))
1904 sio_data->skip_fan |= (1 << 2);
1905
1906 /* Check if fan2 is there or not */
1907 reg29 = superio_inb(IT87_SIO_GPIO5_REG);
1908 if (reg29 & (1 << 1))
1909 sio_data->skip_pwm |= (1 << 1);
1910 if (reg29 & (1 << 2))
1911 sio_data->skip_fan |= (1 << 1);
1912
1913 sio_data->skip_in |= (1 << 5); /* No VIN5 */
1914 sio_data->skip_in |= (1 << 6); /* No VIN6 */
1915
1916 /* no fan4 */
1917 sio_data->skip_pwm |= (1 << 3);
1918 sio_data->skip_fan |= (1 << 3);
1919
1920 sio_data->internal |= (1 << 1); /* in7 is VSB */
1921 sio_data->internal |= (1 << 3); /* in9 is AVCC */
1922
1923 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
Jean Delvare895ff262009-12-09 20:35:47 +01001924 } else {
Jean Delvare87673dd2006-08-28 14:37:19 +02001925 int reg;
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001926 bool uart6;
Jean Delvare87673dd2006-08-28 14:37:19 +02001927
1928 superio_select(GPIO);
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001929
Jean Delvare895ff262009-12-09 20:35:47 +01001930 reg = superio_inb(IT87_SIO_GPIO3_REG);
Guenter Roeck0531d982012-03-02 11:46:44 -08001931 if (sio_data->type == it8721 || sio_data->type == it8728 ||
Guenter Roeckb0636702012-09-07 17:34:41 -06001932 sio_data->type == it8771 || sio_data->type == it8772 ||
Guenter Roeck7bc32d22015-01-17 14:10:24 -08001933 sio_data->type == it8781 || sio_data->type == it8782) {
Jean Delvare16b5dda2012-01-16 22:51:48 +01001934 /*
Guenter Roeck7bc32d22015-01-17 14:10:24 -08001935 * IT8721F/IT8758E, IT8728F, IT8772F, IT8781F, and
1936 * IT8782F don't have VID pins at all, not sure about
1937 * the IT8771F.
Jean Delvare16b5dda2012-01-16 22:51:48 +01001938 */
Jean Delvare895ff262009-12-09 20:35:47 +01001939 sio_data->skip_vid = 1;
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001940 } else {
1941 /* We need at least 4 VID pins */
1942 if (reg & 0x0f) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01001943 pr_info("VID is disabled (pins used for GPIO)\n");
Jean Delvare44c1bcd2010-10-28 20:31:51 +02001944 sio_data->skip_vid = 1;
1945 }
Jean Delvare895ff262009-12-09 20:35:47 +01001946 }
1947
Jean Delvare591ec652009-12-09 20:35:48 +01001948 /* Check if fan3 is there or not */
1949 if (reg & (1 << 6))
1950 sio_data->skip_pwm |= (1 << 2);
1951 if (reg & (1 << 7))
1952 sio_data->skip_fan |= (1 << 2);
1953
1954 /* Check if fan2 is there or not */
1955 reg = superio_inb(IT87_SIO_GPIO5_REG);
1956 if (reg & (1 << 1))
1957 sio_data->skip_pwm |= (1 << 1);
1958 if (reg & (1 << 2))
1959 sio_data->skip_fan |= (1 << 1);
1960
Jean Delvare895ff262009-12-09 20:35:47 +01001961 if ((sio_data->type == it8718 || sio_data->type == it8720)
1962 && !(sio_data->skip_vid))
corentin.labbeb74f3fd2007-06-13 20:27:36 +02001963 sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
Jean Delvare87673dd2006-08-28 14:37:19 +02001964
1965 reg = superio_inb(IT87_SIO_PINX2_REG);
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001966
1967 uart6 = sio_data->type == it8782 && (reg & (1 << 2));
1968
Jean Delvare436cad22010-07-09 16:22:48 +02001969 /*
1970 * The IT8720F has no VIN7 pin, so VCCH should always be
1971 * routed internally to VIN7 with an internal divider.
1972 * Curiously, there still is a configuration bit to control
1973 * this, which means it can be set incorrectly. And even
1974 * more curiously, many boards out there are improperly
1975 * configured, even though the IT8720F datasheet claims
1976 * that the internal routing of VCCH to VIN7 is the default
1977 * setting. So we force the internal routing in this case.
Guenter Roeck0531d982012-03-02 11:46:44 -08001978 *
1979 * On IT8782F, VIN7 is multiplexed with one of the UART6 pins.
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001980 * If UART6 is enabled, re-route VIN7 to the internal divider
1981 * if that is not already the case.
Jean Delvare436cad22010-07-09 16:22:48 +02001982 */
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001983 if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) {
Jean Delvare436cad22010-07-09 16:22:48 +02001984 reg |= (1 << 1);
1985 superio_outb(IT87_SIO_PINX2_REG, reg);
Joe Perchesa8ca1032011-01-12 21:55:10 +01001986 pr_notice("Routing internal VCCH to in7\n");
Jean Delvare436cad22010-07-09 16:22:48 +02001987 }
Jean Delvare87673dd2006-08-28 14:37:19 +02001988 if (reg & (1 << 0))
Jean Delvare738e5e02010-08-14 21:08:50 +02001989 sio_data->internal |= (1 << 0);
Jean Delvare16b5dda2012-01-16 22:51:48 +01001990 if ((reg & (1 << 1)) || sio_data->type == it8721 ||
Guenter Roeckb0636702012-09-07 17:34:41 -06001991 sio_data->type == it8728 ||
1992 sio_data->type == it8771 ||
1993 sio_data->type == it8772)
Jean Delvare738e5e02010-08-14 21:08:50 +02001994 sio_data->internal |= (1 << 1);
Jean Delvared9b327c2010-03-05 22:17:17 +01001995
Guenter Roeck9172b5d2012-03-24 21:49:54 -07001996 /*
1997 * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7.
1998 * While VIN7 can be routed to the internal voltage divider,
1999 * VIN5 and VIN6 are not available if UART6 is enabled.
Guenter Roeck4573acb2012-03-26 16:17:41 -07002000 *
2001 * Also, temp3 is not available if UART6 is enabled and TEMPIN3
2002 * is the temperature source. Since we can not read the
2003 * temperature source here, skip_temp is preliminary.
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002004 */
Guenter Roeck4573acb2012-03-26 16:17:41 -07002005 if (uart6) {
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002006 sio_data->skip_in |= (1 << 5) | (1 << 6);
Guenter Roeck4573acb2012-03-26 16:17:41 -07002007 sio_data->skip_temp |= (1 << 2);
2008 }
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002009
Jean Delvared9b327c2010-03-05 22:17:17 +01002010 sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
Jean Delvare87673dd2006-08-28 14:37:19 +02002011 }
Jean Delvared9b327c2010-03-05 22:17:17 +01002012 if (sio_data->beep_pin)
Joe Perchesa8ca1032011-01-12 21:55:10 +01002013 pr_info("Beeping is supported\n");
Jean Delvare87673dd2006-08-28 14:37:19 +02002014
Jean Delvare98dd22c2008-10-09 15:33:58 +02002015 /* Disable specific features based on DMI strings */
2016 board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
2017 board_name = dmi_get_system_info(DMI_BOARD_NAME);
2018 if (board_vendor && board_name) {
2019 if (strcmp(board_vendor, "nVIDIA") == 0
2020 && strcmp(board_name, "FN68PT") == 0) {
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002021 /*
2022 * On the Shuttle SN68PT, FAN_CTL2 is apparently not
2023 * connected to a fan, but to something else. One user
2024 * has reported instant system power-off when changing
2025 * the PWM2 duty cycle, so we disable it.
2026 * I use the board name string as the trigger in case
2027 * the same board is ever used in other systems.
2028 */
Joe Perchesa8ca1032011-01-12 21:55:10 +01002029 pr_info("Disabling pwm2 due to hardware constraints\n");
Jean Delvare98dd22c2008-10-09 15:33:58 +02002030 sio_data->skip_pwm = (1 << 1);
2031 }
2032 }
2033
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034exit:
2035 superio_exit();
2036 return err;
2037}
2038
Jean Delvare723a0aa2010-03-05 22:17:16 +01002039static void it87_remove_files(struct device *dev)
2040{
2041 struct it87_data *data = platform_get_drvdata(pdev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002042 struct it87_sio_data *sio_data = dev_get_platdata(dev);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002043 int i;
2044
2045 sysfs_remove_group(&dev->kobj, &it87_group);
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002046 for (i = 0; i < 10; i++) {
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002047 if (sio_data->skip_in & (1 << i))
2048 continue;
2049 sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
2050 if (it87_attributes_in_beep[i])
2051 sysfs_remove_file(&dev->kobj,
2052 it87_attributes_in_beep[i]);
2053 }
Guenter Roeck4573acb2012-03-26 16:17:41 -07002054 for (i = 0; i < 3; i++) {
2055 if (!(data->has_temp & (1 << i)))
2056 continue;
2057 sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
Guenter Roeck161d8982012-12-19 22:17:01 +01002058 if (has_temp_offset(data))
2059 sysfs_remove_file(&dev->kobj,
2060 it87_attributes_temp_offset[i]);
Guenter Roeck4573acb2012-03-26 16:17:41 -07002061 if (sio_data->beep_pin)
2062 sysfs_remove_file(&dev->kobj,
2063 it87_attributes_temp_beep[i]);
2064 }
Jean Delvare723a0aa2010-03-05 22:17:16 +01002065 for (i = 0; i < 5; i++) {
2066 if (!(data->has_fan & (1 << i)))
2067 continue;
Guenter Roecke1169ba2012-12-19 22:17:01 +01002068 sysfs_remove_group(&dev->kobj, &it87_group_fan[i]);
Jean Delvared9b327c2010-03-05 22:17:17 +01002069 if (sio_data->beep_pin)
2070 sysfs_remove_file(&dev->kobj,
2071 it87_attributes_fan_beep[i]);
Guenter Roecke1169ba2012-12-19 22:17:01 +01002072 if (i < 3 && !has_16bit_fans(data))
2073 sysfs_remove_file(&dev->kobj,
2074 it87_attributes_fan_div[i]);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002075 }
2076 for (i = 0; i < 3; i++) {
2077 if (sio_data->skip_pwm & (1 << 0))
2078 continue;
2079 sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
Jean Delvare4f3f51b2010-03-05 22:17:21 +01002080 if (has_old_autopwm(data))
2081 sysfs_remove_group(&dev->kobj,
2082 &it87_group_autopwm[i]);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002083 }
Jean Delvare6a8d7ac2010-03-05 22:17:16 +01002084 if (!sio_data->skip_vid)
2085 sysfs_remove_group(&dev->kobj, &it87_group_vid);
Jean Delvare738e5e02010-08-14 21:08:50 +02002086 sysfs_remove_group(&dev->kobj, &it87_group_label);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002087}
2088
Bill Pemberton6c931ae2012-11-19 13:22:35 -05002089static int it87_probe(struct platform_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 struct it87_data *data;
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002092 struct resource *res;
2093 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002094 struct it87_sio_data *sio_data = dev_get_platdata(dev);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002095 int err = 0, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 int enable_pwm_interface;
Jean Delvared9b327c2010-03-05 22:17:17 +01002097 int fan_beep_need_rw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002099 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Guenter Roeck62a1d052012-03-24 21:54:41 -07002100 if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
2101 DRVNAME)) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002102 dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
2103 (unsigned long)res->start,
Bjorn Helgaas87b4b662008-01-22 07:21:03 -05002104 (unsigned long)(res->start + IT87_EC_EXTENT - 1));
Guenter Roeck62a1d052012-03-24 21:54:41 -07002105 return -EBUSY;
Jean Delvare8e9afcb2006-12-12 18:18:28 +01002106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Guenter Roeck62a1d052012-03-24 21:54:41 -07002108 data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL);
2109 if (!data)
2110 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002112 data->addr = res->start;
2113 data->type = sio_data->type;
Guenter Roeck483db432012-12-19 22:17:02 +01002114 data->features = it87_devices[sio_data->type].features;
Guenter Roeck5d8d2f22012-12-19 22:17:02 +01002115 data->peci_mask = it87_devices[sio_data->type].peci_mask;
Guenter Roeck19529782012-12-19 22:17:02 +01002116 data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
Guenter Roeck483db432012-12-19 22:17:02 +01002117 data->name = it87_devices[sio_data->type].name;
2118 /*
2119 * IT8705F Datasheet 0.4.1, 3h == Version G.
2120 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
2121 * These are the first revisions with 16-bit tachometer support.
2122 */
2123 switch (data->type) {
2124 case it87:
2125 if (sio_data->revision >= 0x03) {
2126 data->features &= ~FEAT_OLD_AUTOPWM;
2127 data->features |= FEAT_16BIT_FANS;
2128 }
2129 break;
2130 case it8712:
2131 if (sio_data->revision >= 0x08) {
2132 data->features &= ~FEAT_OLD_AUTOPWM;
2133 data->features |= FEAT_16BIT_FANS;
2134 }
2135 break;
2136 default:
2137 break;
2138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
2140 /* Now, we do the remaining detection. */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002141 if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002142 || it87_read_value(data, IT87_REG_CHIPID) != 0x90)
2143 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002145 platform_set_drvdata(pdev, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146
Ingo Molnar9a61bf62006-01-18 23:19:26 +01002147 mutex_init(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 /* Check PWM configuration */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002150 enable_pwm_interface = it87_check_pwm(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Jean Delvare44c1bcd2010-10-28 20:31:51 +02002152 /* Starting with IT8721F, we handle scaling of internal voltages */
Jean Delvare16b5dda2012-01-16 22:51:48 +01002153 if (has_12mv_adc(data)) {
Jean Delvare44c1bcd2010-10-28 20:31:51 +02002154 if (sio_data->internal & (1 << 0))
2155 data->in_scaled |= (1 << 3); /* in3 is AVCC */
2156 if (sio_data->internal & (1 << 1))
2157 data->in_scaled |= (1 << 7); /* in7 is VSB */
2158 if (sio_data->internal & (1 << 2))
2159 data->in_scaled |= (1 << 8); /* in8 is Vbat */
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002160 if (sio_data->internal & (1 << 3))
2161 data->in_scaled |= (1 << 9); /* in9 is AVCC */
Guenter Roeck7bc32d22015-01-17 14:10:24 -08002162 } else if (sio_data->type == it8781 || sio_data->type == it8782 ||
2163 sio_data->type == it8783) {
Guenter Roeck0531d982012-03-02 11:46:44 -08002164 if (sio_data->internal & (1 << 0))
2165 data->in_scaled |= (1 << 3); /* in3 is VCC5V */
2166 if (sio_data->internal & (1 << 1))
2167 data->in_scaled |= (1 << 7); /* in7 is VCCH5V */
Jean Delvare44c1bcd2010-10-28 20:31:51 +02002168 }
2169
Guenter Roeck4573acb2012-03-26 16:17:41 -07002170 data->has_temp = 0x07;
2171 if (sio_data->skip_temp & (1 << 2)) {
2172 if (sio_data->type == it8782
2173 && !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80))
2174 data->has_temp &= ~(1 << 2);
2175 }
2176
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 /* Initialize the IT87 chip */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002178 it87_init_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
2180 /* Register sysfs hooks */
Jean Delvare5f2dc792010-03-05 22:17:18 +01002181 err = sysfs_create_group(&dev->kobj, &it87_group);
2182 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002183 return err;
Jean Delvare17d648b2006-08-28 14:23:46 +02002184
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002185 for (i = 0; i < 10; i++) {
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002186 if (sio_data->skip_in & (1 << i))
2187 continue;
2188 err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
2189 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002190 goto error;
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002191 if (sio_data->beep_pin && it87_attributes_in_beep[i]) {
2192 err = sysfs_create_file(&dev->kobj,
2193 it87_attributes_in_beep[i]);
2194 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002195 goto error;
Guenter Roeck9172b5d2012-03-24 21:49:54 -07002196 }
2197 }
2198
Guenter Roeck4573acb2012-03-26 16:17:41 -07002199 for (i = 0; i < 3; i++) {
2200 if (!(data->has_temp & (1 << i)))
2201 continue;
2202 err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
Jean Delvared9b327c2010-03-05 22:17:17 +01002203 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002204 goto error;
Guenter Roeck161d8982012-12-19 22:17:01 +01002205 if (has_temp_offset(data)) {
2206 err = sysfs_create_file(&dev->kobj,
2207 it87_attributes_temp_offset[i]);
2208 if (err)
2209 goto error;
2210 }
Guenter Roeck4573acb2012-03-26 16:17:41 -07002211 if (sio_data->beep_pin) {
2212 err = sysfs_create_file(&dev->kobj,
2213 it87_attributes_temp_beep[i]);
2214 if (err)
2215 goto error;
2216 }
Jean Delvared9b327c2010-03-05 22:17:17 +01002217 }
2218
Jean Delvare9060f8b2006-08-28 14:24:17 +02002219 /* Do not create fan files for disabled fans */
Jean Delvared9b327c2010-03-05 22:17:17 +01002220 fan_beep_need_rw = 1;
Jean Delvare723a0aa2010-03-05 22:17:16 +01002221 for (i = 0; i < 5; i++) {
2222 if (!(data->has_fan & (1 << i)))
2223 continue;
Guenter Roecke1169ba2012-12-19 22:17:01 +01002224 err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002225 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002226 goto error;
Jean Delvared9b327c2010-03-05 22:17:17 +01002227
Guenter Roecke1169ba2012-12-19 22:17:01 +01002228 if (i < 3 && !has_16bit_fans(data)) {
2229 err = sysfs_create_file(&dev->kobj,
2230 it87_attributes_fan_div[i]);
2231 if (err)
2232 goto error;
2233 }
2234
Jean Delvared9b327c2010-03-05 22:17:17 +01002235 if (sio_data->beep_pin) {
2236 err = sysfs_create_file(&dev->kobj,
2237 it87_attributes_fan_beep[i]);
2238 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002239 goto error;
Jean Delvared9b327c2010-03-05 22:17:17 +01002240 if (!fan_beep_need_rw)
2241 continue;
2242
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002243 /*
2244 * As we have a single beep enable bit for all fans,
Jean Delvared9b327c2010-03-05 22:17:17 +01002245 * only the first enabled fan has a writable attribute
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002246 * for it.
2247 */
Jean Delvared9b327c2010-03-05 22:17:17 +01002248 if (sysfs_chmod_file(&dev->kobj,
2249 it87_attributes_fan_beep[i],
2250 S_IRUGO | S_IWUSR))
2251 dev_dbg(dev, "chmod +w fan%d_beep failed\n",
2252 i + 1);
2253 fan_beep_need_rw = 0;
2254 }
Jean Delvare17d648b2006-08-28 14:23:46 +02002255 }
2256
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if (enable_pwm_interface) {
Jean Delvare723a0aa2010-03-05 22:17:16 +01002258 for (i = 0; i < 3; i++) {
2259 if (sio_data->skip_pwm & (1 << i))
2260 continue;
2261 err = sysfs_create_group(&dev->kobj,
2262 &it87_group_pwm[i]);
2263 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002264 goto error;
Jean Delvare4f3f51b2010-03-05 22:17:21 +01002265
2266 if (!has_old_autopwm(data))
2267 continue;
2268 err = sysfs_create_group(&dev->kobj,
2269 &it87_group_autopwm[i]);
2270 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002271 goto error;
Jean Delvare98dd22c2008-10-09 15:33:58 +02002272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 }
2274
Jean Delvare895ff262009-12-09 20:35:47 +01002275 if (!sio_data->skip_vid) {
Jean Delvare303760b2005-07-31 21:52:01 +02002276 data->vrm = vid_which_vrm();
Jean Delvare87673dd2006-08-28 14:37:19 +02002277 /* VID reading from Super-I/O config space if available */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002278 data->vid = sio_data->vid_value;
Jean Delvare6a8d7ac2010-03-05 22:17:16 +01002279 err = sysfs_create_group(&dev->kobj, &it87_group_vid);
2280 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002281 goto error;
Jean Delvare87808be2006-09-24 21:17:13 +02002282 }
2283
Jean Delvare738e5e02010-08-14 21:08:50 +02002284 /* Export labels for internal sensors */
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002285 for (i = 0; i < 4; i++) {
Jean Delvare738e5e02010-08-14 21:08:50 +02002286 if (!(sio_data->internal & (1 << i)))
2287 continue;
2288 err = sysfs_create_file(&dev->kobj,
2289 it87_attributes_label[i]);
2290 if (err)
Guenter Roeck62a1d052012-03-24 21:54:41 -07002291 goto error;
Jean Delvare738e5e02010-08-14 21:08:50 +02002292 }
2293
Tony Jones1beeffe2007-08-20 13:46:20 -07002294 data->hwmon_dev = hwmon_device_register(dev);
2295 if (IS_ERR(data->hwmon_dev)) {
2296 err = PTR_ERR(data->hwmon_dev);
Guenter Roeck62a1d052012-03-24 21:54:41 -07002297 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
2299
2300 return 0;
2301
Guenter Roeck62a1d052012-03-24 21:54:41 -07002302error:
Jean Delvare723a0aa2010-03-05 22:17:16 +01002303 it87_remove_files(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 return err;
2305}
2306
Bill Pemberton281dfd02012-11-19 13:25:51 -05002307static int it87_remove(struct platform_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002309 struct it87_data *data = platform_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Tony Jones1beeffe2007-08-20 13:46:20 -07002311 hwmon_device_unregister(data->hwmon_dev);
Jean Delvare723a0aa2010-03-05 22:17:16 +01002312 it87_remove_files(&pdev->dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04002313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 return 0;
2315}
2316
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002317/*
2318 * Must be called with data->update_lock held, except during initialization.
2319 * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
2320 * would slow down the IT87 access and should not be necessary.
2321 */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002322static int it87_read_value(struct it87_data *data, u8 reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002324 outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
2325 return inb_p(data->addr + IT87_DATA_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326}
2327
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002328/*
2329 * Must be called with data->update_lock held, except during initialization.
2330 * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
2331 * would slow down the IT87 access and should not be necessary.
2332 */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002333static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002335 outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
2336 outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337}
2338
2339/* Return 1 if and only if the PWM interface is safe to use */
Bill Pemberton6c931ae2012-11-19 13:22:35 -05002340static int it87_check_pwm(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002342 struct it87_data *data = dev_get_drvdata(dev);
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002343 /*
2344 * Some BIOSes fail to correctly configure the IT87 fans. All fans off
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 * and polarity set to active low is sign that this is the case so we
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002346 * disable pwm control to protect the user.
2347 */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002348 int tmp = it87_read_value(data, IT87_REG_FAN_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 if ((tmp & 0x87) == 0) {
2350 if (fix_pwm_polarity) {
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002351 /*
2352 * The user asks us to attempt a chip reconfiguration.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 * This means switching to active high polarity and
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002354 * inverting all fan speed values.
2355 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 int i;
2357 u8 pwm[3];
2358
2359 for (i = 0; i < 3; i++)
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002360 pwm[i] = it87_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 IT87_REG_PWM(i));
2362
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002363 /*
2364 * If any fan is in automatic pwm mode, the polarity
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 * might be correct, as suspicious as it seems, so we
2366 * better don't change anything (but still disable the
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002367 * PWM interface).
2368 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
Guenter Roeck1d9bcf62012-12-19 22:17:01 +01002370 dev_info(dev,
2371 "Reconfiguring PWM to active high polarity\n");
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002372 it87_write_value(data, IT87_REG_FAN_CTL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 tmp | 0x87);
2374 for (i = 0; i < 3; i++)
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002375 it87_write_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 IT87_REG_PWM(i),
2377 0x7f & ~pwm[i]);
2378 return 1;
2379 }
2380
Guenter Roeck1d9bcf62012-12-19 22:17:01 +01002381 dev_info(dev,
2382 "PWM configuration is too broken to be fixed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 }
2384
Guenter Roeck1d9bcf62012-12-19 22:17:01 +01002385 dev_info(dev,
2386 "Detected broken BIOS defaults, disabling PWM interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 return 0;
2388 } else if (fix_pwm_polarity) {
Guenter Roeck1d9bcf62012-12-19 22:17:01 +01002389 dev_info(dev,
2390 "PWM configuration looks sane, won't touch\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
2392
2393 return 1;
2394}
2395
2396/* Called when we have found a new IT87. */
Bill Pemberton6c931ae2012-11-19 13:22:35 -05002397static void it87_init_device(struct platform_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398{
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002399 struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002400 struct it87_data *data = platform_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 int tmp, i;
Jean Delvare591ec652009-12-09 20:35:48 +01002402 u8 mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002404 /*
2405 * For each PWM channel:
Jean Delvareb99883d2010-03-05 22:17:15 +01002406 * - If it is in automatic mode, setting to manual mode should set
2407 * the fan to full speed by default.
2408 * - If it is in manual mode, we need a mapping to temperature
2409 * channels to use when later setting to automatic mode later.
2410 * Use a 1:1 mapping by default (we are clueless.)
2411 * In both cases, the value can (and should) be changed by the user
Jean Delvare6229cdb2010-12-08 16:27:22 +01002412 * prior to switching to a different mode.
2413 * Note that this is no longer needed for the IT8721F and later, as
2414 * these have separate registers for the temperature mapping and the
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002415 * manual duty cycle.
2416 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 for (i = 0; i < 3; i++) {
Jean Delvareb99883d2010-03-05 22:17:15 +01002418 data->pwm_temp_map[i] = i;
2419 data->pwm_duty[i] = 0x7f; /* Full speed */
Jean Delvare4f3f51b2010-03-05 22:17:21 +01002420 data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
2422
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002423 /*
2424 * Some chips seem to have default value 0xff for all limit
Jean Delvarec5df9b72006-08-28 14:37:54 +02002425 * registers. For low voltage limits it makes no sense and triggers
2426 * alarms, so change to 0 instead. For high temperature limits, it
2427 * means -1 degree C, which surprisingly doesn't trigger an alarm,
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002428 * but is still confusing, so change to 127 degrees C.
2429 */
Jean Delvarec5df9b72006-08-28 14:37:54 +02002430 for (i = 0; i < 8; i++) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002431 tmp = it87_read_value(data, IT87_REG_VIN_MIN(i));
Jean Delvarec5df9b72006-08-28 14:37:54 +02002432 if (tmp == 0xff)
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002433 it87_write_value(data, IT87_REG_VIN_MIN(i), 0);
Jean Delvarec5df9b72006-08-28 14:37:54 +02002434 }
2435 for (i = 0; i < 3; i++) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002436 tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i));
Jean Delvarec5df9b72006-08-28 14:37:54 +02002437 if (tmp == 0xff)
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002438 it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
Jean Delvarec5df9b72006-08-28 14:37:54 +02002439 }
2440
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002441 /*
2442 * Temperature channels are not forcibly enabled, as they can be
Jean Delvarea00afb92010-04-14 16:14:09 +02002443 * set to two different sensor types and we can't guess which one
2444 * is correct for a given system. These channels can be enabled at
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002445 * run-time through the temp{1-3}_type sysfs accessors if needed.
2446 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
2448 /* Check if voltage monitors are reset manually or by some reason */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002449 tmp = it87_read_value(data, IT87_REG_VIN_ENABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 if ((tmp & 0xff) == 0) {
2451 /* Enable all voltage monitors */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002452 it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 }
2454
2455 /* Check if tachometers are reset manually or by some reason */
Jean Delvare591ec652009-12-09 20:35:48 +01002456 mask = 0x70 & ~(sio_data->skip_fan << 4);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002457 data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL);
Jean Delvare591ec652009-12-09 20:35:48 +01002458 if ((data->fan_main_ctrl & mask) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 /* Enable all fan tachometers */
Jean Delvare591ec652009-12-09 20:35:48 +01002460 data->fan_main_ctrl |= mask;
Jean Delvare5f2dc792010-03-05 22:17:18 +01002461 it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
2462 data->fan_main_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
Jean Delvare9060f8b2006-08-28 14:24:17 +02002464 data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002466 /* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?)
2467 * has it by default */
2468 if (has_16bit_fans(data) && data->type != it8603) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002469 tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
Jean Delvare9060f8b2006-08-28 14:24:17 +02002470 if (~tmp & 0x07 & data->has_fan) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002471 dev_dbg(&pdev->dev,
Jean Delvare17d648b2006-08-28 14:23:46 +02002472 "Setting fan1-3 to 16-bit mode\n");
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002473 it87_write_value(data, IT87_REG_FAN_16BIT,
Jean Delvare17d648b2006-08-28 14:23:46 +02002474 tmp | 0x07);
2475 }
Guenter Roeck7bc32d22015-01-17 14:10:24 -08002476 /*
2477 * IT8705F, IT8781F, IT8782F, and IT8783E/F only support
2478 * three fans.
2479 */
2480 if (data->type != it87 && data->type != it8781 &&
2481 data->type != it8782 && data->type != it8783) {
Andrew Paprocki816d8c62008-08-06 22:41:06 +02002482 if (tmp & (1 << 4))
2483 data->has_fan |= (1 << 3); /* fan4 enabled */
2484 if (tmp & (1 << 5))
2485 data->has_fan |= (1 << 4); /* fan5 enabled */
2486 }
Jean Delvare17d648b2006-08-28 14:23:46 +02002487 }
2488
Jean Delvare591ec652009-12-09 20:35:48 +01002489 /* Fan input pins may be used for alternative functions */
2490 data->has_fan &= ~sio_data->skip_fan;
2491
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 /* Start monitoring */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002493 it87_write_value(data, IT87_REG_CONFIG,
Jean Delvare41002f82012-07-12 22:47:37 +02002494 (it87_read_value(data, IT87_REG_CONFIG) & 0x3e)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 | (update_vbat ? 0x41 : 0x01));
2496}
2497
Jean Delvareb99883d2010-03-05 22:17:15 +01002498static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
2499{
2500 data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
Jean Delvare16b5dda2012-01-16 22:51:48 +01002501 if (has_newer_autopwm(data)) {
Jean Delvareb99883d2010-03-05 22:17:15 +01002502 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
Jean Delvare6229cdb2010-12-08 16:27:22 +01002503 data->pwm_duty[nr] = it87_read_value(data,
2504 IT87_REG_PWM_DUTY(nr));
2505 } else {
2506 if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
2507 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
2508 else /* Manual mode */
2509 data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
2510 }
Jean Delvare4f3f51b2010-03-05 22:17:21 +01002511
2512 if (has_old_autopwm(data)) {
2513 int i;
2514
2515 for (i = 0; i < 5 ; i++)
2516 data->auto_temp[nr][i] = it87_read_value(data,
2517 IT87_REG_AUTO_TEMP(nr, i));
2518 for (i = 0; i < 3 ; i++)
2519 data->auto_pwm[nr][i] = it87_read_value(data,
2520 IT87_REG_AUTO_PWM(nr, i));
2521 }
Jean Delvareb99883d2010-03-05 22:17:15 +01002522}
2523
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524static struct it87_data *it87_update_device(struct device *dev)
2525{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002526 struct it87_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 int i;
2528
Ingo Molnar9a61bf62006-01-18 23:19:26 +01002529 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
2531 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
2532 || !data->valid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 if (update_vbat) {
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002534 /*
2535 * Cleared after each update, so reenable. Value
2536 * returned by this read will be previous value
2537 */
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002538 it87_write_value(data, IT87_REG_CONFIG,
Jean Delvare5f2dc792010-03-05 22:17:18 +01002539 it87_read_value(data, IT87_REG_CONFIG) | 0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 }
2541 for (i = 0; i <= 7; i++) {
Guenter Roeck929c6a52012-12-19 22:17:00 +01002542 data->in[i][0] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002543 it87_read_value(data, IT87_REG_VIN(i));
Guenter Roeck929c6a52012-12-19 22:17:00 +01002544 data->in[i][1] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002545 it87_read_value(data, IT87_REG_VIN_MIN(i));
Guenter Roeck929c6a52012-12-19 22:17:00 +01002546 data->in[i][2] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002547 it87_read_value(data, IT87_REG_VIN_MAX(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 }
Jean Delvare3543a532006-08-28 14:27:25 +02002549 /* in8 (battery) has no limit registers */
Guenter Roeck929c6a52012-12-19 22:17:00 +01002550 data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
Rudolf Marekc145d5c2014-01-29 20:40:08 +01002551 if (data->type == it8603)
2552 data->in[9][0] = it87_read_value(data, 0x2f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
Jean Delvarec7f1f712007-09-03 17:11:46 +02002554 for (i = 0; i < 5; i++) {
Jean Delvare9060f8b2006-08-28 14:24:17 +02002555 /* Skip disabled fans */
2556 if (!(data->has_fan & (1 << i)))
2557 continue;
2558
Guenter Roecke1169ba2012-12-19 22:17:01 +01002559 data->fan[i][1] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002560 it87_read_value(data, IT87_REG_FAN_MIN[i]);
Guenter Roecke1169ba2012-12-19 22:17:01 +01002561 data->fan[i][0] = it87_read_value(data,
Jean Delvarec7f1f712007-09-03 17:11:46 +02002562 IT87_REG_FAN[i]);
Jean Delvare17d648b2006-08-28 14:23:46 +02002563 /* Add high byte if in 16-bit mode */
Andrew Paprocki04751692008-08-06 22:41:06 +02002564 if (has_16bit_fans(data)) {
Guenter Roecke1169ba2012-12-19 22:17:01 +01002565 data->fan[i][0] |= it87_read_value(data,
Jean Delvarec7f1f712007-09-03 17:11:46 +02002566 IT87_REG_FANX[i]) << 8;
Guenter Roecke1169ba2012-12-19 22:17:01 +01002567 data->fan[i][1] |= it87_read_value(data,
Jean Delvarec7f1f712007-09-03 17:11:46 +02002568 IT87_REG_FANX_MIN[i]) << 8;
Jean Delvare17d648b2006-08-28 14:23:46 +02002569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 }
2571 for (i = 0; i < 3; i++) {
Guenter Roeck4573acb2012-03-26 16:17:41 -07002572 if (!(data->has_temp & (1 << i)))
2573 continue;
Guenter Roeck60ca3852012-12-19 22:17:00 +01002574 data->temp[i][0] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002575 it87_read_value(data, IT87_REG_TEMP(i));
Guenter Roeck60ca3852012-12-19 22:17:00 +01002576 data->temp[i][1] =
Jean Delvare5f2dc792010-03-05 22:17:18 +01002577 it87_read_value(data, IT87_REG_TEMP_LOW(i));
Guenter Roeck60ca3852012-12-19 22:17:00 +01002578 data->temp[i][2] =
2579 it87_read_value(data, IT87_REG_TEMP_HIGH(i));
Guenter Roeck161d8982012-12-19 22:17:01 +01002580 if (has_temp_offset(data))
2581 data->temp[i][3] =
2582 it87_read_value(data,
2583 IT87_REG_TEMP_OFFSET[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 }
2585
Jean Delvare17d648b2006-08-28 14:23:46 +02002586 /* Newer chips don't have clock dividers */
Andrew Paprocki04751692008-08-06 22:41:06 +02002587 if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002588 i = it87_read_value(data, IT87_REG_FAN_DIV);
Jean Delvare17d648b2006-08-28 14:23:46 +02002589 data->fan_div[0] = i & 0x07;
2590 data->fan_div[1] = (i >> 3) & 0x07;
2591 data->fan_div[2] = (i & 0x40) ? 3 : 1;
2592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
2594 data->alarms =
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002595 it87_read_value(data, IT87_REG_ALARM1) |
2596 (it87_read_value(data, IT87_REG_ALARM2) << 8) |
2597 (it87_read_value(data, IT87_REG_ALARM3) << 16);
Jean Delvared9b327c2010-03-05 22:17:17 +01002598 data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
Jean Delvareb99883d2010-03-05 22:17:15 +01002599
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002600 data->fan_main_ctrl = it87_read_value(data,
2601 IT87_REG_FAN_MAIN_CTRL);
2602 data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
Jean Delvareb99883d2010-03-05 22:17:15 +01002603 for (i = 0; i < 3; i++)
2604 it87_update_pwm_ctrl(data, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002606 data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
Guenter Roeck19529782012-12-19 22:17:02 +01002607 data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002608 /*
2609 * The IT8705F does not have VID capability.
2610 * The IT8718F and later don't use IT87_REG_VID for the
2611 * same purpose.
2612 */
Jean Delvare17d648b2006-08-28 14:23:46 +02002613 if (data->type == it8712 || data->type == it8716) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002614 data->vid = it87_read_value(data, IT87_REG_VID);
Guenter Roeck4a0d71c2012-01-19 11:02:18 -08002615 /*
2616 * The older IT8712F revisions had only 5 VID pins,
2617 * but we assume it is always safe to read 6 bits.
2618 */
Jean Delvare17d648b2006-08-28 14:23:46 +02002619 data->vid &= 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 }
2621 data->last_updated = jiffies;
2622 data->valid = 1;
2623 }
2624
Ingo Molnar9a61bf62006-01-18 23:19:26 +01002625 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
2627 return data;
2628}
2629
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002630static int __init it87_device_add(unsigned short address,
2631 const struct it87_sio_data *sio_data)
2632{
2633 struct resource res = {
Bjorn Helgaas87b4b662008-01-22 07:21:03 -05002634 .start = address + IT87_EC_OFFSET,
2635 .end = address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1,
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002636 .name = DRVNAME,
2637 .flags = IORESOURCE_IO,
2638 };
2639 int err;
2640
Jean Delvareb9acb642009-01-07 16:37:35 +01002641 err = acpi_check_resource_conflict(&res);
2642 if (err)
2643 goto exit;
2644
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002645 pdev = platform_device_alloc(DRVNAME, address);
2646 if (!pdev) {
2647 err = -ENOMEM;
Joe Perchesa8ca1032011-01-12 21:55:10 +01002648 pr_err("Device allocation failed\n");
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002649 goto exit;
2650 }
2651
2652 err = platform_device_add_resources(pdev, &res, 1);
2653 if (err) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01002654 pr_err("Device resource addition failed (%d)\n", err);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002655 goto exit_device_put;
2656 }
2657
2658 err = platform_device_add_data(pdev, sio_data,
2659 sizeof(struct it87_sio_data));
2660 if (err) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01002661 pr_err("Platform data allocation failed\n");
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002662 goto exit_device_put;
2663 }
2664
2665 err = platform_device_add(pdev);
2666 if (err) {
Joe Perchesa8ca1032011-01-12 21:55:10 +01002667 pr_err("Device addition failed (%d)\n", err);
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002668 goto exit_device_put;
2669 }
2670
2671 return 0;
2672
2673exit_device_put:
2674 platform_device_put(pdev);
2675exit:
2676 return err;
2677}
2678
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679static int __init sm_it87_init(void)
2680{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002681 int err;
Jean Delvare5f2dc792010-03-05 22:17:18 +01002682 unsigned short isa_address = 0;
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002683 struct it87_sio_data sio_data;
Jean Delvarefde09502005-07-19 23:51:07 +02002684
Jean Delvare98dd22c2008-10-09 15:33:58 +02002685 memset(&sio_data, 0, sizeof(struct it87_sio_data));
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002686 err = it87_find(&isa_address, &sio_data);
2687 if (err)
2688 return err;
2689 err = platform_driver_register(&it87_driver);
2690 if (err)
2691 return err;
2692
2693 err = it87_device_add(isa_address, &sio_data);
Jean Delvare5f2dc792010-03-05 22:17:18 +01002694 if (err) {
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002695 platform_driver_unregister(&it87_driver);
2696 return err;
2697 }
2698
2699 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700}
2701
2702static void __exit sm_it87_exit(void)
2703{
corentin.labbeb74f3fd2007-06-13 20:27:36 +02002704 platform_device_unregister(pdev);
2705 platform_driver_unregister(&it87_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706}
2707
2708
Jean Delvare7c81c602014-01-29 20:40:08 +01002709MODULE_AUTHOR("Chris Gauthron, Jean Delvare <jdelvare@suse.de>");
Jean Delvare44c1bcd2010-10-28 20:31:51 +02002710MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711module_param(update_vbat, bool, 0);
2712MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
2713module_param(fix_pwm_polarity, bool, 0);
Jean Delvare5f2dc792010-03-05 22:17:18 +01002714MODULE_PARM_DESC(fix_pwm_polarity,
2715 "Force PWM polarity to active high (DANGEROUS)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716MODULE_LICENSE("GPL");
2717
2718module_init(sm_it87_init);
2719module_exit(sm_it87_exit);