blob: eb171d15ac489ec12792e22c072751942a79f108 [file] [log] [blame]
Thomas Gleixner74ba9202019-05-20 09:19:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Jean Delvare08e7e272005-04-25 22:43:25 +02002/*
Guenter Roeck8969e842012-01-19 11:02:27 -08003 * w83627ehf - Driver for the hardware monitoring functionality of
4 * the Winbond W83627EHF Super-I/O chip
Jean Delvare7c81c60f2014-01-29 20:40:08 +01005 * Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>
Guenter Roeck8969e842012-01-19 11:02:27 -08006 * Copyright (C) 2006 Yuan Mu (Winbond),
7 * Rudolf Marek <r.marek@assembler.cz>
8 * David Hubbard <david.c.hubbard@gmail.com>
9 * Daniel J Blueman <daniel.blueman@gmail.com>
10 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
11 *
12 * Shamelessly ripped from the w83627hf driver
13 * Copyright (C) 2003 Mark Studebaker
14 *
15 * Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
16 * in testing and debugging this driver.
17 *
18 * This driver also supports the W83627EHG, which is the lead-free
19 * version of the W83627EHF.
20 *
Guenter Roeck8969e842012-01-19 11:02:27 -080021 * Supports the following chips:
22 *
23 * Chip #vin #fan #pwm #temp chip IDs man ID
24 * w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3
25 * 0x8860 0xa1
26 * w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3
27 * w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3
28 * w83627uhg 8 2 2 3 0xa230 0xc1 0x5ca3
29 * w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3
30 * w83667hg-b 9 5 3 4 0xb350 0xc1 0x5ca3
31 * nct6775f 9 4 3 9 0xb470 0xc1 0x5ca3
32 * nct6776f 9 5 3 9 0xC330 0xc1 0x5ca3
33 */
Jean Delvare08e7e272005-04-25 22:43:25 +020034
Joe Perchesabdc6fd2010-10-20 06:51:54 +000035#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
36
Jean Delvare08e7e272005-04-25 22:43:25 +020037#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/slab.h>
David Hubbard1ea6dd32007-06-24 11:16:15 +020040#include <linux/jiffies.h>
41#include <linux/platform_device.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040042#include <linux/hwmon.h>
Yuan Mu412fec82006-02-05 23:24:16 +010043#include <linux/hwmon-sysfs.h>
Jean Delvarefc18d6c2007-06-24 11:19:42 +020044#include <linux/hwmon-vid.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040045#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010046#include <linux/mutex.h>
Jean Delvareb9acb642009-01-07 16:37:35 +010047#include <linux/acpi.h>
H Hartley Sweeten6055fae2009-09-15 17:18:13 +020048#include <linux/io.h>
Jean Delvare08e7e272005-04-25 22:43:25 +020049#include "lm75.h"
50
Jean Delvareeff76872011-11-04 12:00:48 +010051enum kinds {
52 w83627ehf, w83627dhg, w83627dhg_p, w83627uhg,
53 w83667hg, w83667hg_b, nct6775, nct6776,
54};
David Hubbard1ea6dd32007-06-24 11:16:15 +020055
56/* used to set data->name = w83627ehf_device_names[data->sio_kind] */
Guenter Roecke7e1ca62011-02-04 13:24:30 -080057static const char * const w83627ehf_device_names[] = {
David Hubbard1ea6dd32007-06-24 11:16:15 +020058 "w83627ehf",
59 "w83627dhg",
Jean Delvarec1e48dc2009-06-15 18:39:50 +020060 "w83627dhg",
Jean Delvareeff76872011-11-04 12:00:48 +010061 "w83627uhg",
Gong Jun237c8d2f2009-03-30 21:46:42 +020062 "w83667hg",
Guenter Roeckc39aeda2010-08-14 21:08:55 +020063 "w83667hg",
Guenter Roeckec3e5a162011-02-02 08:46:49 -080064 "nct6775",
65 "nct6776",
David Hubbard1ea6dd32007-06-24 11:16:15 +020066};
67
Jean Delvare67b671b2007-12-06 23:13:42 +010068static unsigned short force_id;
69module_param(force_id, ushort, 0);
70MODULE_PARM_DESC(force_id, "Override the detected device ID");
71
Ian Dobsond42e869a2011-03-07 14:21:12 -080072static unsigned short fan_debounce;
73module_param(fan_debounce, ushort, 0);
74MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
75
David Hubbard1ea6dd32007-06-24 11:16:15 +020076#define DRVNAME "w83627ehf"
Jean Delvare08e7e272005-04-25 22:43:25 +020077
78/*
79 * Super-I/O constants and functions
80 */
81
Jean Delvare08e7e272005-04-25 22:43:25 +020082#define W83627EHF_LD_HWM 0x0b
Guenter Roecke7e1ca62011-02-04 13:24:30 -080083#define W83667HG_LD_VID 0x0d
Jean Delvare08e7e272005-04-25 22:43:25 +020084
85#define SIO_REG_LDSEL 0x07 /* Logical device select */
86#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
Jean Delvarefc18d6c2007-06-24 11:19:42 +020087#define SIO_REG_EN_VRM10 0x2C /* GPIO3, GPIO4 selection */
Jean Delvare08e7e272005-04-25 22:43:25 +020088#define SIO_REG_ENABLE 0x30 /* Logical device enable */
89#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
Jean Delvarefc18d6c2007-06-24 11:19:42 +020090#define SIO_REG_VID_CTRL 0xF0 /* VID control */
91#define SIO_REG_VID_DATA 0xF1 /* VID data */
Jean Delvare08e7e272005-04-25 22:43:25 +020092
David Hubbard657c93b2007-02-14 21:15:04 +010093#define SIO_W83627EHF_ID 0x8850
94#define SIO_W83627EHG_ID 0x8860
95#define SIO_W83627DHG_ID 0xa020
Jean Delvarec1e48dc2009-06-15 18:39:50 +020096#define SIO_W83627DHG_P_ID 0xb070
Jean Delvareeff76872011-11-04 12:00:48 +010097#define SIO_W83627UHG_ID 0xa230
Guenter Roecke7e1ca62011-02-04 13:24:30 -080098#define SIO_W83667HG_ID 0xa510
Guenter Roeckc39aeda2010-08-14 21:08:55 +020099#define SIO_W83667HG_B_ID 0xb350
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800100#define SIO_NCT6775_ID 0xb470
101#define SIO_NCT6776_ID 0xc330
David Hubbard657c93b2007-02-14 21:15:04 +0100102#define SIO_ID_MASK 0xFFF0
Jean Delvare08e7e272005-04-25 22:43:25 +0200103
104static inline void
David Hubbard1ea6dd32007-06-24 11:16:15 +0200105superio_outb(int ioreg, int reg, int val)
Jean Delvare08e7e272005-04-25 22:43:25 +0200106{
David Hubbard1ea6dd32007-06-24 11:16:15 +0200107 outb(reg, ioreg);
108 outb(val, ioreg + 1);
Jean Delvare08e7e272005-04-25 22:43:25 +0200109}
110
111static inline int
David Hubbard1ea6dd32007-06-24 11:16:15 +0200112superio_inb(int ioreg, int reg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200113{
David Hubbard1ea6dd32007-06-24 11:16:15 +0200114 outb(reg, ioreg);
115 return inb(ioreg + 1);
Jean Delvare08e7e272005-04-25 22:43:25 +0200116}
117
118static inline void
David Hubbard1ea6dd32007-06-24 11:16:15 +0200119superio_select(int ioreg, int ld)
Jean Delvare08e7e272005-04-25 22:43:25 +0200120{
David Hubbard1ea6dd32007-06-24 11:16:15 +0200121 outb(SIO_REG_LDSEL, ioreg);
122 outb(ld, ioreg + 1);
Jean Delvare08e7e272005-04-25 22:43:25 +0200123}
124
Katsumi Sato0d023532017-02-22 13:32:10 +0900125static inline int
David Hubbard1ea6dd32007-06-24 11:16:15 +0200126superio_enter(int ioreg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200127{
Katsumi Sato0d023532017-02-22 13:32:10 +0900128 if (!request_muxed_region(ioreg, 2, DRVNAME))
129 return -EBUSY;
130
David Hubbard1ea6dd32007-06-24 11:16:15 +0200131 outb(0x87, ioreg);
132 outb(0x87, ioreg);
Katsumi Sato0d023532017-02-22 13:32:10 +0900133
134 return 0;
Jean Delvare08e7e272005-04-25 22:43:25 +0200135}
136
137static inline void
David Hubbard1ea6dd32007-06-24 11:16:15 +0200138superio_exit(int ioreg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200139{
Jonas Jonsson022b75a2010-09-17 17:24:13 +0200140 outb(0xaa, ioreg);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200141 outb(0x02, ioreg);
142 outb(0x02, ioreg + 1);
Katsumi Sato0d023532017-02-22 13:32:10 +0900143 release_region(ioreg, 2);
Jean Delvare08e7e272005-04-25 22:43:25 +0200144}
145
146/*
147 * ISA constants
148 */
149
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800150#define IOREGION_ALIGNMENT (~7)
Jean Delvare1a641fc2007-04-23 14:41:16 -0700151#define IOREGION_OFFSET 5
152#define IOREGION_LENGTH 2
David Hubbard1ea6dd32007-06-24 11:16:15 +0200153#define ADDR_REG_OFFSET 0
154#define DATA_REG_OFFSET 1
Jean Delvare08e7e272005-04-25 22:43:25 +0200155
156#define W83627EHF_REG_BANK 0x4E
157#define W83627EHF_REG_CONFIG 0x40
David Hubbard657c93b2007-02-14 21:15:04 +0100158
Guenter Roeck8969e842012-01-19 11:02:27 -0800159/*
160 * Not currently used:
David Hubbard657c93b2007-02-14 21:15:04 +0100161 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
162 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
163 * REG_MAN_ID is at port 0x4f
Guenter Roeck8969e842012-01-19 11:02:27 -0800164 * REG_CHIP_ID is at port 0x58
165 */
Jean Delvare08e7e272005-04-25 22:43:25 +0200166
167static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
168static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
169
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100170/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
171#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
172 (0x554 + (((nr) - 7) * 2)))
173#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
174 (0x555 + (((nr) - 7) * 2)))
175#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
176 (0x550 + (nr) - 7))
177
Guenter Roeckd36cf322011-02-07 15:08:54 -0800178static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e };
179static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 };
180static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 };
181static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };
Jean Delvare08e7e272005-04-25 22:43:25 +0200182
183/* Fan clock dividers are spread over the following five registers */
184#define W83627EHF_REG_FANDIV1 0x47
185#define W83627EHF_REG_FANDIV2 0x4B
186#define W83627EHF_REG_VBAT 0x5D
187#define W83627EHF_REG_DIODE 0x59
188#define W83627EHF_REG_SMI_OVT 0x4C
189
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800190/* NCT6775F has its own fan divider registers */
191#define NCT6775_REG_FANDIV1 0x506
192#define NCT6775_REG_FANDIV2 0x507
Ian Dobsond42e869a2011-03-07 14:21:12 -0800193#define NCT6775_REG_FAN_DEBOUNCE 0xf0
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800194
Jean Delvarea4589db2006-03-23 16:30:29 +0100195#define W83627EHF_REG_ALARM1 0x459
196#define W83627EHF_REG_ALARM2 0x45A
197#define W83627EHF_REG_ALARM3 0x45B
198
Dmitry Artamonow363a12a2011-08-12 16:41:11 -0400199#define W83627EHF_REG_CASEOPEN_DET 0x42 /* SMI STATUS #2 */
200#define W83627EHF_REG_CASEOPEN_CLR 0x46 /* SMI MASK #3 */
201
Rudolf Marek08c79952006-07-05 18:14:31 +0200202/* SmartFan registers */
Daniel J Blueman41e9a062009-12-14 18:01:37 -0800203#define W83627EHF_REG_FAN_STEPUP_TIME 0x0f
204#define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e
205
Rudolf Marek08c79952006-07-05 18:14:31 +0200206/* DC or PWM output fan configuration */
207static const u8 W83627EHF_REG_PWM_ENABLE[] = {
208 0x04, /* SYS FAN0 output mode and PWM mode */
209 0x04, /* CPU FAN0 output mode and PWM mode */
210 0x12, /* AUX FAN mode */
Daniel J Blueman41e9a062009-12-14 18:01:37 -0800211 0x62, /* CPU FAN1 mode */
Rudolf Marek08c79952006-07-05 18:14:31 +0200212};
213
214static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
215static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
216
217/* FAN Duty Cycle, be used to control */
Guenter Roeck279af1a2011-02-13 22:34:47 -0800218static const u16 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
219static const u16 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
Rudolf Marek08c79952006-07-05 18:14:31 +0200220static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
221
Rudolf Marek08c79952006-07-05 18:14:31 +0200222/* Advanced Fan control, some values are common for all fans */
Guenter Roeck279af1a2011-02-13 22:34:47 -0800223static const u16 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
224static const u16 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
225static const u16 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
Guenter Roeckc39aeda2010-08-14 21:08:55 +0200226
Guenter Roeck279af1a2011-02-13 22:34:47 -0800227static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
Guenter Roeckc39aeda2010-08-14 21:08:55 +0200228 = { 0xff, 0x67, 0xff, 0x69 };
Guenter Roeck279af1a2011-02-13 22:34:47 -0800229static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
Guenter Roeckc39aeda2010-08-14 21:08:55 +0200230 = { 0xff, 0x68, 0xff, 0x6a };
231
Guenter Roeck279af1a2011-02-13 22:34:47 -0800232static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
233static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[]
234 = { 0x68, 0x6a, 0x6c };
Rudolf Marek08c79952006-07-05 18:14:31 +0200235
Guenter Roeck840e1912012-02-08 09:29:11 -0800236static const u16 W83627EHF_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
237
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800238static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 };
239static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 };
240static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 };
241static const u16 NCT6775_REG_FAN_START_OUTPUT[] = { 0x106, 0x206, 0x306 };
242static const u16 NCT6775_REG_FAN_STOP_TIME[] = { 0x107, 0x207, 0x307 };
243static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309 };
244static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
245static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
Guenter Roeck26bc4402011-02-11 08:00:58 -0800246static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800247static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642};
248
249static const u16 NCT6775_REG_TEMP[]
250 = { 0x27, 0x150, 0x250, 0x73, 0x75, 0x77, 0x62b, 0x62c, 0x62d };
251static const u16 NCT6775_REG_TEMP_CONFIG[]
252 = { 0, 0x152, 0x252, 0, 0, 0, 0x628, 0x629, 0x62A };
253static const u16 NCT6775_REG_TEMP_HYST[]
254 = { 0x3a, 0x153, 0x253, 0, 0, 0, 0x673, 0x678, 0x67D };
255static const u16 NCT6775_REG_TEMP_OVER[]
256 = { 0x39, 0x155, 0x255, 0, 0, 0, 0x672, 0x677, 0x67C };
257static const u16 NCT6775_REG_TEMP_SOURCE[]
258 = { 0x621, 0x622, 0x623, 0x100, 0x200, 0x300, 0x624, 0x625, 0x626 };
259
Guenter Roeckd36cf322011-02-07 15:08:54 -0800260static const char *const w83667hg_b_temp_label[] = {
261 "SYSTIN",
262 "CPUTIN",
263 "AUXTIN",
264 "AMDTSI",
265 "PECI Agent 1",
266 "PECI Agent 2",
267 "PECI Agent 3",
268 "PECI Agent 4"
269};
270
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800271static const char *const nct6775_temp_label[] = {
272 "",
273 "SYSTIN",
274 "CPUTIN",
275 "AUXTIN",
276 "AMD SB-TSI",
277 "PECI Agent 0",
278 "PECI Agent 1",
279 "PECI Agent 2",
280 "PECI Agent 3",
281 "PECI Agent 4",
282 "PECI Agent 5",
283 "PECI Agent 6",
284 "PECI Agent 7",
285 "PCH_CHIP_CPU_MAX_TEMP",
286 "PCH_CHIP_TEMP",
287 "PCH_CPU_TEMP",
288 "PCH_MCH_TEMP",
289 "PCH_DIM0_TEMP",
290 "PCH_DIM1_TEMP",
291 "PCH_DIM2_TEMP",
292 "PCH_DIM3_TEMP"
293};
294
295static const char *const nct6776_temp_label[] = {
296 "",
297 "SYSTIN",
298 "CPUTIN",
299 "AUXTIN",
300 "SMBUSMASTER 0",
301 "SMBUSMASTER 1",
302 "SMBUSMASTER 2",
303 "SMBUSMASTER 3",
304 "SMBUSMASTER 4",
305 "SMBUSMASTER 5",
306 "SMBUSMASTER 6",
307 "SMBUSMASTER 7",
308 "PECI Agent 0",
309 "PECI Agent 1",
310 "PCH_CHIP_CPU_MAX_TEMP",
311 "PCH_CHIP_TEMP",
312 "PCH_CPU_TEMP",
313 "PCH_MCH_TEMP",
314 "PCH_DIM0_TEMP",
315 "PCH_DIM1_TEMP",
316 "PCH_DIM2_TEMP",
317 "PCH_DIM3_TEMP",
318 "BYTE_TEMP"
319};
320
321#define NUM_REG_TEMP ARRAY_SIZE(NCT6775_REG_TEMP)
Guenter Roeckd36cf322011-02-07 15:08:54 -0800322
Jean Delvare17296fe2011-10-20 03:08:27 -0400323static int is_word_sized(u16 reg)
Guenter Roeckbce26c52011-02-04 12:54:14 -0800324{
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800325 return ((((reg & 0xff00) == 0x100
Guenter Roeckbce26c52011-02-04 12:54:14 -0800326 || (reg & 0xff00) == 0x200)
327 && ((reg & 0x00ff) == 0x50
328 || (reg & 0x00ff) == 0x53
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800329 || (reg & 0x00ff) == 0x55))
330 || (reg & 0xfff0) == 0x630
331 || reg == 0x640 || reg == 0x642
332 || ((reg & 0xfff0) == 0x650
333 && (reg & 0x000f) >= 0x06)
334 || reg == 0x73 || reg == 0x75 || reg == 0x77
335 );
Guenter Roeckbce26c52011-02-04 12:54:14 -0800336}
337
Jean Delvare08e7e272005-04-25 22:43:25 +0200338/*
339 * Conversions
340 */
341
Rudolf Marek08c79952006-07-05 18:14:31 +0200342/* 1 is PWM mode, output in ms */
343static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
344{
345 return mode ? 100 * reg : 400 * reg;
346}
347
348static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
349{
Guenter Roeck2a844c12013-01-09 08:09:34 -0800350 return clamp_val((mode ? (msec + 50) / 100 : (msec + 200) / 400),
351 1, 255);
Rudolf Marek08c79952006-07-05 18:14:31 +0200352}
353
Guenter Roeck26bc4402011-02-11 08:00:58 -0800354static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200355{
Guenter Roeck26bc4402011-02-11 08:00:58 -0800356 if (reg == 0 || reg == 255)
Jean Delvare08e7e272005-04-25 22:43:25 +0200357 return 0;
Guenter Roeck26bc4402011-02-11 08:00:58 -0800358 return 1350000U / (reg << divreg);
359}
360
361static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
362{
363 if ((reg & 0xff1f) == 0xff1f)
364 return 0;
365
366 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
367
368 if (reg == 0)
369 return 0;
370
371 return 1350000U / reg;
372}
373
374static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
375{
376 if (reg == 0 || reg == 0xffff)
377 return 0;
378
379 /*
380 * Even though the registers are 16 bit wide, the fan divisor
381 * still applies.
382 */
383 return 1350000U / (reg << divreg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200384}
385
386static inline unsigned int
387div_from_reg(u8 reg)
388{
389 return 1 << reg;
390}
391
Guenter Roeck8969e842012-01-19 11:02:27 -0800392/*
393 * Some of the voltage inputs have internal scaling, the tables below
394 * contain 8 (the ADC LSB in mV) * scaling factor * 100
395 */
Jean Delvareeff76872011-11-04 12:00:48 +0100396static const u16 scale_in_common[10] = {
397 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800
398};
399static const u16 scale_in_w83627uhg[9] = {
400 800, 800, 3328, 3424, 800, 800, 0, 3328, 3400
401};
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100402
Jean Delvareeff76872011-11-04 12:00:48 +0100403static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100404{
Jean Delvareeff76872011-11-04 12:00:48 +0100405 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100406}
407
Jean Delvareeff76872011-11-04 12:00:48 +0100408static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100409{
Guenter Roeck2a844c12013-01-09 08:09:34 -0800410 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100411}
412
Jean Delvare08e7e272005-04-25 22:43:25 +0200413/*
414 * Data structures and manipulation thereof
415 */
416
417struct w83627ehf_data {
David Hubbard1ea6dd32007-06-24 11:16:15 +0200418 int addr; /* IO base of hw monitor block */
419 const char *name;
420
Tony Jones1beeffe2007-08-20 13:46:20 -0700421 struct device *hwmon_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100422 struct mutex lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200423
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800424 u16 reg_temp[NUM_REG_TEMP];
425 u16 reg_temp_over[NUM_REG_TEMP];
426 u16 reg_temp_hyst[NUM_REG_TEMP];
427 u16 reg_temp_config[NUM_REG_TEMP];
Guenter Roeckd36cf322011-02-07 15:08:54 -0800428 u8 temp_src[NUM_REG_TEMP];
429 const char * const *temp_label;
430
Guenter Roeck279af1a2011-02-13 22:34:47 -0800431 const u16 *REG_PWM;
432 const u16 *REG_TARGET;
433 const u16 *REG_FAN;
434 const u16 *REG_FAN_MIN;
435 const u16 *REG_FAN_START_OUTPUT;
436 const u16 *REG_FAN_STOP_OUTPUT;
437 const u16 *REG_FAN_STOP_TIME;
438 const u16 *REG_FAN_MAX_OUTPUT;
439 const u16 *REG_FAN_STEP_OUTPUT;
Jean Delvareeff76872011-11-04 12:00:48 +0100440 const u16 *scale_in;
Guenter Roeckda2e0252010-08-14 21:08:55 +0200441
Guenter Roeck26bc4402011-02-11 08:00:58 -0800442 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
443 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
444
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100445 struct mutex update_lock;
Jean Delvare08e7e272005-04-25 22:43:25 +0200446 char valid; /* !=0 if following fields are valid */
447 unsigned long last_updated; /* In jiffies */
448
449 /* Register values */
Guenter Roeck83cc8982011-02-06 08:10:15 -0800450 u8 bank; /* current register bank */
David Hubbard1ea6dd32007-06-24 11:16:15 +0200451 u8 in_num; /* number of in inputs we have */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100452 u8 in[10]; /* Register value */
453 u8 in_max[10]; /* Register value */
454 u8 in_min[10]; /* Register value */
Guenter Roeck3382a912011-02-13 13:08:23 -0800455 unsigned int rpm[5];
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800456 u16 fan_min[5];
Jean Delvare08e7e272005-04-25 22:43:25 +0200457 u8 fan_div[5];
458 u8 has_fan; /* some fan inputs can be disabled */
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800459 u8 has_fan_min; /* some fans don't have min register */
Guenter Roeck26bc4402011-02-11 08:00:58 -0800460 bool has_fan_div;
Jean Delvareda667362007-06-24 11:21:02 +0200461 u8 temp_type[3];
Guenter Roeck840e1912012-02-08 09:29:11 -0800462 s8 temp_offset[3];
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800463 s16 temp[9];
464 s16 temp_max[9];
465 s16 temp_max_hyst[9];
Jean Delvarea4589db2006-03-23 16:30:29 +0100466 u32 alarms;
Dmitry Artamonow363a12a2011-08-12 16:41:11 -0400467 u8 caseopen;
Rudolf Marek08c79952006-07-05 18:14:31 +0200468
469 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
470 u8 pwm_enable[4]; /* 1->manual
Guenter Roeck8969e842012-01-19 11:02:27 -0800471 * 2->thermal cruise mode (also called SmartFan I)
472 * 3->fan speed cruise mode
473 * 4->variable thermal cruise (also called
474 * SmartFan III)
475 * 5->enhanced variable thermal cruise (also called
476 * SmartFan IV)
477 */
Guenter Roeckb84bb512011-02-13 23:01:25 -0800478 u8 pwm_enable_orig[4]; /* original value of pwm_enable */
Gong Jun237c8d2f2009-03-30 21:46:42 +0200479 u8 pwm_num; /* number of pwm */
Rudolf Marek08c79952006-07-05 18:14:31 +0200480 u8 pwm[4];
481 u8 target_temp[4];
482 u8 tolerance[4];
483
Daniel J Blueman41e9a062009-12-14 18:01:37 -0800484 u8 fan_start_output[4]; /* minimum fan speed when spinning up */
485 u8 fan_stop_output[4]; /* minimum fan speed when spinning down */
486 u8 fan_stop_time[4]; /* time at minimum before disabling fan */
487 u8 fan_max_output[4]; /* maximum fan speed */
488 u8 fan_step_output[4]; /* rate of change output value */
Jean Delvarefc18d6c2007-06-24 11:19:42 +0200489
490 u8 vid;
491 u8 vrm;
Gong Juna157d062009-03-30 21:46:43 +0200492
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800493 u16 have_temp;
Guenter Roeck840e1912012-02-08 09:29:11 -0800494 u16 have_temp_offset;
Jean Delvareeff76872011-11-04 12:00:48 +0100495 u8 in6_skip:1;
496 u8 temp3_val_only:1;
Jean Delvare7e630bb2012-12-19 22:16:59 +0100497
498#ifdef CONFIG_PM
499 /* Remember extra register values over suspend/resume */
500 u8 vbat;
501 u8 fandiv1;
502 u8 fandiv2;
503#endif
Jean Delvare08e7e272005-04-25 22:43:25 +0200504};
505
David Hubbard1ea6dd32007-06-24 11:16:15 +0200506struct w83627ehf_sio_data {
507 int sioreg;
508 enum kinds kind;
509};
510
Guenter Roeck83cc8982011-02-06 08:10:15 -0800511/*
512 * On older chips, only registers 0x50-0x5f are banked.
513 * On more recent chips, all registers are banked.
514 * Assume that is the case and set the bank number for each access.
515 * Cache the bank number so it only needs to be set if it changes.
516 */
David Hubbard1ea6dd32007-06-24 11:16:15 +0200517static inline void w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200518{
Guenter Roeck83cc8982011-02-06 08:10:15 -0800519 u8 bank = reg >> 8;
520 if (data->bank != bank) {
David Hubbard1ea6dd32007-06-24 11:16:15 +0200521 outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
Guenter Roeck83cc8982011-02-06 08:10:15 -0800522 outb_p(bank, data->addr + DATA_REG_OFFSET);
523 data->bank = bank;
Jean Delvare08e7e272005-04-25 22:43:25 +0200524 }
525}
526
David Hubbard1ea6dd32007-06-24 11:16:15 +0200527static u16 w83627ehf_read_value(struct w83627ehf_data *data, u16 reg)
Jean Delvare08e7e272005-04-25 22:43:25 +0200528{
Jean Delvare08e7e272005-04-25 22:43:25 +0200529 int res, word_sized = is_word_sized(reg);
530
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100531 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200532
David Hubbard1ea6dd32007-06-24 11:16:15 +0200533 w83627ehf_set_bank(data, reg);
534 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
535 res = inb_p(data->addr + DATA_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200536 if (word_sized) {
537 outb_p((reg & 0xff) + 1,
David Hubbard1ea6dd32007-06-24 11:16:15 +0200538 data->addr + ADDR_REG_OFFSET);
539 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200540 }
Jean Delvare08e7e272005-04-25 22:43:25 +0200541
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100542 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200543 return res;
544}
545
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800546static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg,
547 u16 value)
Jean Delvare08e7e272005-04-25 22:43:25 +0200548{
Jean Delvare08e7e272005-04-25 22:43:25 +0200549 int word_sized = is_word_sized(reg);
550
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100551 mutex_lock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200552
David Hubbard1ea6dd32007-06-24 11:16:15 +0200553 w83627ehf_set_bank(data, reg);
554 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200555 if (word_sized) {
David Hubbard1ea6dd32007-06-24 11:16:15 +0200556 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200557 outb_p((reg & 0xff) + 1,
David Hubbard1ea6dd32007-06-24 11:16:15 +0200558 data->addr + ADDR_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200559 }
David Hubbard1ea6dd32007-06-24 11:16:15 +0200560 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Jean Delvare08e7e272005-04-25 22:43:25 +0200561
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100562 mutex_unlock(&data->lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200563 return 0;
564}
565
Jean Delvarec5794cf2011-10-20 03:13:31 -0400566/* We left-align 8-bit temperature values to make the code simpler */
567static u16 w83627ehf_read_temp(struct w83627ehf_data *data, u16 reg)
568{
569 u16 res;
570
571 res = w83627ehf_read_value(data, reg);
572 if (!is_word_sized(reg))
573 res <<= 8;
574
575 return res;
576}
577
578static int w83627ehf_write_temp(struct w83627ehf_data *data, u16 reg,
579 u16 value)
580{
581 if (!is_word_sized(reg))
582 value >>= 8;
583 return w83627ehf_write_value(data, reg, value);
584}
585
Jean Delvare08e7e272005-04-25 22:43:25 +0200586/* This function assumes that the caller holds data->update_lock */
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800587static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
588{
589 u8 reg;
590
591 switch (nr) {
592 case 0:
593 reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
594 | (data->fan_div[0] & 0x7);
595 w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
596 break;
597 case 1:
598 reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
599 | ((data->fan_div[1] << 4) & 0x70);
600 w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
Guenter Roeck58c36672012-06-21 06:32:40 -0700601 break;
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800602 case 2:
603 reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
604 | (data->fan_div[2] & 0x7);
605 w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
606 break;
607 case 3:
608 reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
609 | ((data->fan_div[3] << 4) & 0x70);
610 w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
611 break;
612 }
613}
614
615/* This function assumes that the caller holds data->update_lock */
David Hubbard1ea6dd32007-06-24 11:16:15 +0200616static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
Jean Delvare08e7e272005-04-25 22:43:25 +0200617{
Jean Delvare08e7e272005-04-25 22:43:25 +0200618 u8 reg;
619
620 switch (nr) {
621 case 0:
David Hubbard1ea6dd32007-06-24 11:16:15 +0200622 reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0xcf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200623 | ((data->fan_div[0] & 0x03) << 4);
Rudolf Marek14992c72006-10-08 22:02:09 +0200624 /* fan5 input control bit is write only, compute the value */
625 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
David Hubbard1ea6dd32007-06-24 11:16:15 +0200626 w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg);
627 reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xdf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200628 | ((data->fan_div[0] & 0x04) << 3);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200629 w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200630 break;
631 case 1:
David Hubbard1ea6dd32007-06-24 11:16:15 +0200632 reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0x3f)
Jean Delvare08e7e272005-04-25 22:43:25 +0200633 | ((data->fan_div[1] & 0x03) << 6);
Rudolf Marek14992c72006-10-08 22:02:09 +0200634 /* fan5 input control bit is write only, compute the value */
635 reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
David Hubbard1ea6dd32007-06-24 11:16:15 +0200636 w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg);
637 reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xbf)
Jean Delvare08e7e272005-04-25 22:43:25 +0200638 | ((data->fan_div[1] & 0x04) << 4);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200639 w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200640 break;
641 case 2:
David Hubbard1ea6dd32007-06-24 11:16:15 +0200642 reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f)
Jean Delvare08e7e272005-04-25 22:43:25 +0200643 | ((data->fan_div[2] & 0x03) << 6);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200644 w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg);
645 reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f)
Jean Delvare08e7e272005-04-25 22:43:25 +0200646 | ((data->fan_div[2] & 0x04) << 5);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200647 w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200648 break;
649 case 3:
David Hubbard1ea6dd32007-06-24 11:16:15 +0200650 reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc)
Jean Delvare08e7e272005-04-25 22:43:25 +0200651 | (data->fan_div[3] & 0x03);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200652 w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);
653 reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f)
Jean Delvare08e7e272005-04-25 22:43:25 +0200654 | ((data->fan_div[3] & 0x04) << 5);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200655 w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200656 break;
657 case 4:
David Hubbard1ea6dd32007-06-24 11:16:15 +0200658 reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73)
Jean Delvare33725ad2007-04-17 00:32:27 -0700659 | ((data->fan_div[4] & 0x03) << 2)
Jean Delvare08e7e272005-04-25 22:43:25 +0200660 | ((data->fan_div[4] & 0x04) << 5);
David Hubbard1ea6dd32007-06-24 11:16:15 +0200661 w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);
Jean Delvare08e7e272005-04-25 22:43:25 +0200662 break;
663 }
664}
665
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800666static void w83627ehf_write_fan_div_common(struct device *dev,
667 struct w83627ehf_data *data, int nr)
668{
Jingoo Hana8b3a3a2013-07-30 17:13:06 +0900669 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800670
671 if (sio_data->kind == nct6776)
672 ; /* no dividers, do nothing */
673 else if (sio_data->kind == nct6775)
674 nct6775_write_fan_div(data, nr);
675 else
676 w83627ehf_write_fan_div(data, nr);
677}
678
679static void nct6775_update_fan_div(struct w83627ehf_data *data)
680{
681 u8 i;
682
683 i = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
684 data->fan_div[0] = i & 0x7;
685 data->fan_div[1] = (i & 0x70) >> 4;
686 i = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
687 data->fan_div[2] = i & 0x7;
688 if (data->has_fan & (1<<3))
689 data->fan_div[3] = (i & 0x70) >> 4;
690}
691
Mark M. Hoffmanea7be662007-08-05 12:19:01 -0400692static void w83627ehf_update_fan_div(struct w83627ehf_data *data)
693{
694 int i;
695
696 i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
697 data->fan_div[0] = (i >> 4) & 0x03;
698 data->fan_div[1] = (i >> 6) & 0x03;
699 i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2);
700 data->fan_div[2] = (i >> 6) & 0x03;
701 i = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
702 data->fan_div[0] |= (i >> 3) & 0x04;
703 data->fan_div[1] |= (i >> 4) & 0x04;
704 data->fan_div[2] |= (i >> 5) & 0x04;
705 if (data->has_fan & ((1 << 3) | (1 << 4))) {
706 i = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
707 data->fan_div[3] = i & 0x03;
708 data->fan_div[4] = ((i >> 2) & 0x03)
709 | ((i >> 5) & 0x04);
710 }
711 if (data->has_fan & (1 << 3)) {
712 i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT);
713 data->fan_div[3] |= (i >> 5) & 0x04;
714 }
715}
716
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800717static void w83627ehf_update_fan_div_common(struct device *dev,
718 struct w83627ehf_data *data)
719{
Jingoo Hana8b3a3a2013-07-30 17:13:06 +0900720 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800721
722 if (sio_data->kind == nct6776)
723 ; /* no dividers, do nothing */
724 else if (sio_data->kind == nct6775)
725 nct6775_update_fan_div(data);
726 else
727 w83627ehf_update_fan_div(data);
728}
729
730static void nct6775_update_pwm(struct w83627ehf_data *data)
731{
732 int i;
733 int pwmcfg, fanmodecfg;
734
735 for (i = 0; i < data->pwm_num; i++) {
736 pwmcfg = w83627ehf_read_value(data,
737 W83627EHF_REG_PWM_ENABLE[i]);
738 fanmodecfg = w83627ehf_read_value(data,
739 NCT6775_REG_FAN_MODE[i]);
740 data->pwm_mode[i] =
741 ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
742 data->pwm_enable[i] = ((fanmodecfg >> 4) & 7) + 1;
743 data->tolerance[i] = fanmodecfg & 0x0f;
744 data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
745 }
746}
747
748static void w83627ehf_update_pwm(struct w83627ehf_data *data)
749{
750 int i;
751 int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
752
753 for (i = 0; i < data->pwm_num; i++) {
754 if (!(data->has_fan & (1 << i)))
755 continue;
756
757 /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
758 if (i != 1) {
759 pwmcfg = w83627ehf_read_value(data,
760 W83627EHF_REG_PWM_ENABLE[i]);
761 tolerance = w83627ehf_read_value(data,
762 W83627EHF_REG_TOLERANCE[i]);
763 }
764 data->pwm_mode[i] =
765 ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
766 data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
767 & 3) + 1;
768 data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
769
770 data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) & 0x0f;
771 }
772}
773
774static void w83627ehf_update_pwm_common(struct device *dev,
775 struct w83627ehf_data *data)
776{
Jingoo Hana8b3a3a2013-07-30 17:13:06 +0900777 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800778
779 if (sio_data->kind == nct6775 || sio_data->kind == nct6776)
780 nct6775_update_pwm(data);
781 else
782 w83627ehf_update_pwm(data);
783}
784
Jean Delvare08e7e272005-04-25 22:43:25 +0200785static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
786{
David Hubbard1ea6dd32007-06-24 11:16:15 +0200787 struct w83627ehf_data *data = dev_get_drvdata(dev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +0900788 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800789
Jean Delvare08e7e272005-04-25 22:43:25 +0200790 int i;
791
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100792 mutex_lock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200793
Jean Delvare6b3e4642007-06-24 11:19:01 +0200794 if (time_after(jiffies, data->last_updated + HZ + HZ/2)
Jean Delvare08e7e272005-04-25 22:43:25 +0200795 || !data->valid) {
796 /* Fan clock dividers */
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800797 w83627ehf_update_fan_div_common(dev, data);
Jean Delvare08e7e272005-04-25 22:43:25 +0200798
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100799 /* Measured voltages and limits */
David Hubbard1ea6dd32007-06-24 11:16:15 +0200800 for (i = 0; i < data->in_num; i++) {
Jean Delvare389ef652011-10-13 10:40:53 -0400801 if ((i == 6) && data->in6_skip)
802 continue;
803
David Hubbard1ea6dd32007-06-24 11:16:15 +0200804 data->in[i] = w83627ehf_read_value(data,
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100805 W83627EHF_REG_IN(i));
David Hubbard1ea6dd32007-06-24 11:16:15 +0200806 data->in_min[i] = w83627ehf_read_value(data,
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100807 W83627EHF_REG_IN_MIN(i));
David Hubbard1ea6dd32007-06-24 11:16:15 +0200808 data->in_max[i] = w83627ehf_read_value(data,
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100809 W83627EHF_REG_IN_MAX(i));
810 }
811
Jean Delvare08e7e272005-04-25 22:43:25 +0200812 /* Measured fan speeds and limits */
813 for (i = 0; i < 5; i++) {
Guenter Roeck3382a912011-02-13 13:08:23 -0800814 u16 reg;
815
Jean Delvare08e7e272005-04-25 22:43:25 +0200816 if (!(data->has_fan & (1 << i)))
817 continue;
818
Guenter Roeck3382a912011-02-13 13:08:23 -0800819 reg = w83627ehf_read_value(data, data->REG_FAN[i]);
820 data->rpm[i] = data->fan_from_reg(reg,
821 data->fan_div[i]);
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800822
823 if (data->has_fan_min & (1 << i))
824 data->fan_min[i] = w83627ehf_read_value(data,
Guenter Roeck279af1a2011-02-13 22:34:47 -0800825 data->REG_FAN_MIN[i]);
Jean Delvare08e7e272005-04-25 22:43:25 +0200826
Guenter Roeck8969e842012-01-19 11:02:27 -0800827 /*
828 * If we failed to measure the fan speed and clock
829 * divider can be increased, let's try that for next
830 * time
831 */
Guenter Roeck26bc4402011-02-11 08:00:58 -0800832 if (data->has_fan_div
Guenter Roeck3382a912011-02-13 13:08:23 -0800833 && (reg >= 0xff || (sio_data->kind == nct6775
834 && reg == 0x00))
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800835 && data->fan_div[i] < 0x07) {
Guenter Roeckb55f3752013-01-10 10:01:24 -0800836 dev_dbg(dev,
837 "Increasing fan%d clock divider from %u to %u\n",
Jean Delvare33725ad2007-04-17 00:32:27 -0700838 i + 1, div_from_reg(data->fan_div[i]),
Jean Delvare08e7e272005-04-25 22:43:25 +0200839 div_from_reg(data->fan_div[i] + 1));
840 data->fan_div[i]++;
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800841 w83627ehf_write_fan_div_common(dev, data, i);
Jean Delvare08e7e272005-04-25 22:43:25 +0200842 /* Preserve min limit if possible */
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800843 if ((data->has_fan_min & (1 << i))
844 && data->fan_min[i] >= 2
Jean Delvare08e7e272005-04-25 22:43:25 +0200845 && data->fan_min[i] != 255)
David Hubbard1ea6dd32007-06-24 11:16:15 +0200846 w83627ehf_write_value(data,
Guenter Roeck279af1a2011-02-13 22:34:47 -0800847 data->REG_FAN_MIN[i],
Jean Delvare08e7e272005-04-25 22:43:25 +0200848 (data->fan_min[i] /= 2));
849 }
850 }
851
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800852 w83627ehf_update_pwm_common(dev, data);
853
Guenter Roeckda2e0252010-08-14 21:08:55 +0200854 for (i = 0; i < data->pwm_num; i++) {
855 if (!(data->has_fan & (1 << i)))
856 continue;
857
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800858 data->fan_start_output[i] =
859 w83627ehf_read_value(data,
860 data->REG_FAN_START_OUTPUT[i]);
861 data->fan_stop_output[i] =
862 w83627ehf_read_value(data,
863 data->REG_FAN_STOP_OUTPUT[i]);
864 data->fan_stop_time[i] =
865 w83627ehf_read_value(data,
866 data->REG_FAN_STOP_TIME[i]);
Guenter Roeckda2e0252010-08-14 21:08:55 +0200867
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800868 if (data->REG_FAN_MAX_OUTPUT &&
869 data->REG_FAN_MAX_OUTPUT[i] != 0xff)
Guenter Roeckda2e0252010-08-14 21:08:55 +0200870 data->fan_max_output[i] =
871 w83627ehf_read_value(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800872 data->REG_FAN_MAX_OUTPUT[i]);
Guenter Roeckda2e0252010-08-14 21:08:55 +0200873
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800874 if (data->REG_FAN_STEP_OUTPUT &&
875 data->REG_FAN_STEP_OUTPUT[i] != 0xff)
Guenter Roeckda2e0252010-08-14 21:08:55 +0200876 data->fan_step_output[i] =
877 w83627ehf_read_value(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800878 data->REG_FAN_STEP_OUTPUT[i]);
Guenter Roeckda2e0252010-08-14 21:08:55 +0200879
Rudolf Marek08c79952006-07-05 18:14:31 +0200880 data->target_temp[i] =
David Hubbard1ea6dd32007-06-24 11:16:15 +0200881 w83627ehf_read_value(data,
Guenter Roeck279af1a2011-02-13 22:34:47 -0800882 data->REG_TARGET[i]) &
Rudolf Marek08c79952006-07-05 18:14:31 +0200883 (data->pwm_mode[i] == 1 ? 0x7f : 0xff);
Rudolf Marek08c79952006-07-05 18:14:31 +0200884 }
885
Jean Delvare08e7e272005-04-25 22:43:25 +0200886 /* Measured temperatures and limits */
Guenter Roeckd36cf322011-02-07 15:08:54 -0800887 for (i = 0; i < NUM_REG_TEMP; i++) {
888 if (!(data->have_temp & (1 << i)))
889 continue;
Jean Delvarec5794cf2011-10-20 03:13:31 -0400890 data->temp[i] = w83627ehf_read_temp(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800891 data->reg_temp[i]);
892 if (data->reg_temp_over[i])
893 data->temp_max[i]
Jean Delvarec5794cf2011-10-20 03:13:31 -0400894 = w83627ehf_read_temp(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800895 data->reg_temp_over[i]);
896 if (data->reg_temp_hyst[i])
897 data->temp_max_hyst[i]
Jean Delvarec5794cf2011-10-20 03:13:31 -0400898 = w83627ehf_read_temp(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -0800899 data->reg_temp_hyst[i]);
Jean Delvare45633fb2012-12-19 22:17:00 +0100900 if (i > 2)
901 continue;
Guenter Roeck840e1912012-02-08 09:29:11 -0800902 if (data->have_temp_offset & (1 << i))
903 data->temp_offset[i]
904 = w83627ehf_read_value(data,
905 W83627EHF_REG_TEMP_OFFSET[i]);
Jean Delvare08e7e272005-04-25 22:43:25 +0200906 }
907
David Hubbard1ea6dd32007-06-24 11:16:15 +0200908 data->alarms = w83627ehf_read_value(data,
Jean Delvarea4589db2006-03-23 16:30:29 +0100909 W83627EHF_REG_ALARM1) |
David Hubbard1ea6dd32007-06-24 11:16:15 +0200910 (w83627ehf_read_value(data,
Jean Delvarea4589db2006-03-23 16:30:29 +0100911 W83627EHF_REG_ALARM2) << 8) |
David Hubbard1ea6dd32007-06-24 11:16:15 +0200912 (w83627ehf_read_value(data,
Jean Delvarea4589db2006-03-23 16:30:29 +0100913 W83627EHF_REG_ALARM3) << 16);
914
Dmitry Artamonow363a12a2011-08-12 16:41:11 -0400915 data->caseopen = w83627ehf_read_value(data,
916 W83627EHF_REG_CASEOPEN_DET);
917
Jean Delvare08e7e272005-04-25 22:43:25 +0200918 data->last_updated = jiffies;
919 data->valid = 1;
920 }
921
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100922 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +0200923 return data;
924}
925
926/*
927 * Sysfs callback functions
928 */
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100929#define show_in_reg(reg) \
930static ssize_t \
931show_##reg(struct device *dev, struct device_attribute *attr, \
932 char *buf) \
933{ \
934 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800935 struct sensor_device_attribute *sensor_attr = \
936 to_sensor_dev_attr(attr); \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100937 int nr = sensor_attr->index; \
Jean Delvareeff76872011-11-04 12:00:48 +0100938 return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \
939 data->scale_in)); \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100940}
941show_in_reg(in)
942show_in_reg(in_min)
943show_in_reg(in_max)
944
945#define store_in_reg(REG, reg) \
946static ssize_t \
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800947store_in_##reg(struct device *dev, struct device_attribute *attr, \
948 const char *buf, size_t count) \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100949{ \
David Hubbard1ea6dd32007-06-24 11:16:15 +0200950 struct w83627ehf_data *data = dev_get_drvdata(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800951 struct sensor_device_attribute *sensor_attr = \
952 to_sensor_dev_attr(attr); \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100953 int nr = sensor_attr->index; \
Guenter Roeckbce26c52011-02-04 12:54:14 -0800954 unsigned long val; \
955 int err; \
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +0100956 err = kstrtoul(buf, 10, &val); \
Guenter Roeckbce26c52011-02-04 12:54:14 -0800957 if (err < 0) \
958 return err; \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100959 mutex_lock(&data->update_lock); \
Jean Delvareeff76872011-11-04 12:00:48 +0100960 data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \
David Hubbard1ea6dd32007-06-24 11:16:15 +0200961 w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100962 data->in_##reg[nr]); \
963 mutex_unlock(&data->update_lock); \
964 return count; \
965}
966
967store_in_reg(MIN, min)
968store_in_reg(MAX, max)
969
Guenter Roecke7e1ca62011-02-04 13:24:30 -0800970static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
971 char *buf)
Jean Delvarea4589db2006-03-23 16:30:29 +0100972{
973 struct w83627ehf_data *data = w83627ehf_update_device(dev);
974 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
975 int nr = sensor_attr->index;
976 return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01);
977}
978
Rudolf Marekcf0676f2006-03-23 16:25:22 +0100979static struct sensor_device_attribute sda_in_input[] = {
980 SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
981 SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
982 SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
983 SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
984 SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
985 SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
986 SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
987 SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
988 SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
989 SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
990};
991
Jean Delvarea4589db2006-03-23 16:30:29 +0100992static struct sensor_device_attribute sda_in_alarm[] = {
993 SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
994 SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
995 SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
996 SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
997 SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
998 SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21),
999 SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20),
1000 SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16),
1001 SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17),
1002 SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),
1003};
1004
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001005static struct sensor_device_attribute sda_in_min[] = {
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001006 SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
1007 SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
1008 SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
1009 SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
1010 SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
1011 SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
1012 SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
1013 SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
1014 SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
1015 SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001016};
1017
1018static struct sensor_device_attribute sda_in_max[] = {
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001019 SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
1020 SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
1021 SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
1022 SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
1023 SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
1024 SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
1025 SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
1026 SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
1027 SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
1028 SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
Rudolf Marekcf0676f2006-03-23 16:25:22 +01001029};
1030
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001031static ssize_t
1032show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1033{
1034 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1035 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1036 int nr = sensor_attr->index;
Guenter Roeck3382a912011-02-13 13:08:23 -08001037 return sprintf(buf, "%d\n", data->rpm[nr]);
Jean Delvare08e7e272005-04-25 22:43:25 +02001038}
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001039
1040static ssize_t
1041show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1042{
1043 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1044 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1045 int nr = sensor_attr->index;
1046 return sprintf(buf, "%d\n",
Guenter Roeck26bc4402011-02-11 08:00:58 -08001047 data->fan_from_reg_min(data->fan_min[nr],
1048 data->fan_div[nr]));
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001049}
Jean Delvare08e7e272005-04-25 22:43:25 +02001050
1051static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +01001052show_fan_div(struct device *dev, struct device_attribute *attr,
1053 char *buf)
Jean Delvare08e7e272005-04-25 22:43:25 +02001054{
1055 struct w83627ehf_data *data = w83627ehf_update_device(dev);
Yuan Mu412fec82006-02-05 23:24:16 +01001056 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1057 int nr = sensor_attr->index;
1058 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
Jean Delvare08e7e272005-04-25 22:43:25 +02001059}
1060
1061static ssize_t
Yuan Mu412fec82006-02-05 23:24:16 +01001062store_fan_min(struct device *dev, struct device_attribute *attr,
1063 const char *buf, size_t count)
Jean Delvare08e7e272005-04-25 22:43:25 +02001064{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001065 struct w83627ehf_data *data = dev_get_drvdata(dev);
Yuan Mu412fec82006-02-05 23:24:16 +01001066 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1067 int nr = sensor_attr->index;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001068 unsigned long val;
1069 int err;
Jean Delvare08e7e272005-04-25 22:43:25 +02001070 unsigned int reg;
1071 u8 new_div;
1072
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001073 err = kstrtoul(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001074 if (err < 0)
1075 return err;
1076
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001077 mutex_lock(&data->update_lock);
Guenter Roeck26bc4402011-02-11 08:00:58 -08001078 if (!data->has_fan_div) {
1079 /*
1080 * Only NCT6776F for now, so we know that this is a 13 bit
1081 * register
1082 */
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001083 if (!val) {
1084 val = 0xff1f;
1085 } else {
1086 if (val > 1350000U)
1087 val = 135000U;
1088 val = 1350000U / val;
1089 val = (val & 0x1f) | ((val << 3) & 0xff00);
1090 }
1091 data->fan_min[nr] = val;
1092 goto done; /* Leave fan divider alone */
1093 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001094 if (!val) {
1095 /* No min limit, alarm disabled */
1096 data->fan_min[nr] = 255;
1097 new_div = data->fan_div[nr]; /* No change */
1098 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1099 } else if ((reg = 1350000U / val) >= 128 * 255) {
Guenter Roeck8969e842012-01-19 11:02:27 -08001100 /*
1101 * Speed below this value cannot possibly be represented,
1102 * even with the highest divider (128)
1103 */
Jean Delvare08e7e272005-04-25 22:43:25 +02001104 data->fan_min[nr] = 254;
1105 new_div = 7; /* 128 == (1 << 7) */
Guenter Roeckb55f3752013-01-10 10:01:24 -08001106 dev_warn(dev,
1107 "fan%u low limit %lu below minimum %u, set to minimum\n",
1108 nr + 1, val, data->fan_from_reg_min(254, 7));
Jean Delvare08e7e272005-04-25 22:43:25 +02001109 } else if (!reg) {
Guenter Roeck8969e842012-01-19 11:02:27 -08001110 /*
1111 * Speed above this value cannot possibly be represented,
1112 * even with the lowest divider (1)
1113 */
Jean Delvare08e7e272005-04-25 22:43:25 +02001114 data->fan_min[nr] = 1;
1115 new_div = 0; /* 1 == (1 << 0) */
Guenter Roeckb55f3752013-01-10 10:01:24 -08001116 dev_warn(dev,
1117 "fan%u low limit %lu above maximum %u, set to maximum\n",
1118 nr + 1, val, data->fan_from_reg_min(1, 0));
Jean Delvare08e7e272005-04-25 22:43:25 +02001119 } else {
Guenter Roeck8969e842012-01-19 11:02:27 -08001120 /*
1121 * Automatically pick the best divider, i.e. the one such
1122 * that the min limit will correspond to a register value
1123 * in the 96..192 range
1124 */
Jean Delvare08e7e272005-04-25 22:43:25 +02001125 new_div = 0;
1126 while (reg > 192 && new_div < 7) {
1127 reg >>= 1;
1128 new_div++;
1129 }
1130 data->fan_min[nr] = reg;
1131 }
1132
Guenter Roeck8969e842012-01-19 11:02:27 -08001133 /*
1134 * Write both the fan clock divider (if it changed) and the new
1135 * fan min (unconditionally)
1136 */
Jean Delvare08e7e272005-04-25 22:43:25 +02001137 if (new_div != data->fan_div[nr]) {
Jean Delvare08e7e272005-04-25 22:43:25 +02001138 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1139 nr + 1, div_from_reg(data->fan_div[nr]),
1140 div_from_reg(new_div));
1141 data->fan_div[nr] = new_div;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001142 w83627ehf_write_fan_div_common(dev, data, nr);
Jean Delvare6b3e4642007-06-24 11:19:01 +02001143 /* Give the chip time to sample a new speed value */
1144 data->last_updated = jiffies;
Jean Delvare08e7e272005-04-25 22:43:25 +02001145 }
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001146done:
Guenter Roeck279af1a2011-02-13 22:34:47 -08001147 w83627ehf_write_value(data, data->REG_FAN_MIN[nr],
Jean Delvare08e7e272005-04-25 22:43:25 +02001148 data->fan_min[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001149 mutex_unlock(&data->update_lock);
Jean Delvare08e7e272005-04-25 22:43:25 +02001150
1151 return count;
1152}
1153
Yuan Mu412fec82006-02-05 23:24:16 +01001154static struct sensor_device_attribute sda_fan_input[] = {
1155 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
1156 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
1157 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
1158 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
1159 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
1160};
Jean Delvare08e7e272005-04-25 22:43:25 +02001161
Jean Delvarea4589db2006-03-23 16:30:29 +01001162static struct sensor_device_attribute sda_fan_alarm[] = {
1163 SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
1164 SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
1165 SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
1166 SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10),
1167 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),
1168};
1169
Yuan Mu412fec82006-02-05 23:24:16 +01001170static struct sensor_device_attribute sda_fan_min[] = {
1171 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
1172 store_fan_min, 0),
1173 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
1174 store_fan_min, 1),
1175 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
1176 store_fan_min, 2),
1177 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
1178 store_fan_min, 3),
1179 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
1180 store_fan_min, 4),
1181};
Jean Delvare08e7e272005-04-25 22:43:25 +02001182
Yuan Mu412fec82006-02-05 23:24:16 +01001183static struct sensor_device_attribute sda_fan_div[] = {
1184 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
1185 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
1186 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
1187 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
1188 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
1189};
Jean Delvare08e7e272005-04-25 22:43:25 +02001190
Guenter Roeckd36cf322011-02-07 15:08:54 -08001191static ssize_t
1192show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1193{
1194 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1195 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1196 int nr = sensor_attr->index;
1197 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1198}
1199
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001200#define show_temp_reg(addr, reg) \
Jean Delvare08e7e272005-04-25 22:43:25 +02001201static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +01001202show_##reg(struct device *dev, struct device_attribute *attr, \
1203 char *buf) \
Jean Delvare08e7e272005-04-25 22:43:25 +02001204{ \
1205 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001206 struct sensor_device_attribute *sensor_attr = \
1207 to_sensor_dev_attr(attr); \
Yuan Mu412fec82006-02-05 23:24:16 +01001208 int nr = sensor_attr->index; \
Jean Delvarec5794cf2011-10-20 03:13:31 -04001209 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->reg[nr])); \
Jean Delvare08e7e272005-04-25 22:43:25 +02001210}
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001211show_temp_reg(reg_temp, temp);
1212show_temp_reg(reg_temp_over, temp_max);
1213show_temp_reg(reg_temp_hyst, temp_max_hyst);
Jean Delvare08e7e272005-04-25 22:43:25 +02001214
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001215#define store_temp_reg(addr, reg) \
Jean Delvare08e7e272005-04-25 22:43:25 +02001216static ssize_t \
Yuan Mu412fec82006-02-05 23:24:16 +01001217store_##reg(struct device *dev, struct device_attribute *attr, \
1218 const char *buf, size_t count) \
Jean Delvare08e7e272005-04-25 22:43:25 +02001219{ \
David Hubbard1ea6dd32007-06-24 11:16:15 +02001220 struct w83627ehf_data *data = dev_get_drvdata(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001221 struct sensor_device_attribute *sensor_attr = \
1222 to_sensor_dev_attr(attr); \
Yuan Mu412fec82006-02-05 23:24:16 +01001223 int nr = sensor_attr->index; \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001224 int err; \
1225 long val; \
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001226 err = kstrtol(buf, 10, &val); \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001227 if (err < 0) \
1228 return err; \
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001229 mutex_lock(&data->update_lock); \
Jean Delvarec5794cf2011-10-20 03:13:31 -04001230 data->reg[nr] = LM75_TEMP_TO_REG(val); \
1231 w83627ehf_write_temp(data, data->addr[nr], data->reg[nr]); \
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001232 mutex_unlock(&data->update_lock); \
Jean Delvare08e7e272005-04-25 22:43:25 +02001233 return count; \
1234}
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001235store_temp_reg(reg_temp_over, temp_max);
1236store_temp_reg(reg_temp_hyst, temp_max_hyst);
Jean Delvare08e7e272005-04-25 22:43:25 +02001237
Jean Delvareda667362007-06-24 11:21:02 +02001238static ssize_t
Guenter Roeck840e1912012-02-08 09:29:11 -08001239show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1240{
1241 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1242 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1243
1244 return sprintf(buf, "%d\n",
1245 data->temp_offset[sensor_attr->index] * 1000);
1246}
1247
1248static ssize_t
1249store_temp_offset(struct device *dev, struct device_attribute *attr,
1250 const char *buf, size_t count)
1251{
1252 struct w83627ehf_data *data = dev_get_drvdata(dev);
1253 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1254 int nr = sensor_attr->index;
1255 long val;
1256 int err;
1257
1258 err = kstrtol(buf, 10, &val);
1259 if (err < 0)
1260 return err;
1261
Guenter Roeck2a844c12013-01-09 08:09:34 -08001262 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
Guenter Roeck840e1912012-02-08 09:29:11 -08001263
1264 mutex_lock(&data->update_lock);
1265 data->temp_offset[nr] = val;
1266 w83627ehf_write_value(data, W83627EHF_REG_TEMP_OFFSET[nr], val);
1267 mutex_unlock(&data->update_lock);
1268 return count;
1269}
1270
1271static ssize_t
Jean Delvareda667362007-06-24 11:21:02 +02001272show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1273{
1274 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1275 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1276 int nr = sensor_attr->index;
1277 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1278}
1279
Gong Juna157d062009-03-30 21:46:43 +02001280static struct sensor_device_attribute sda_temp_input[] = {
Guenter Roeckbce26c52011-02-04 12:54:14 -08001281 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
1282 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
1283 SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
Guenter Roeckd36cf322011-02-07 15:08:54 -08001284 SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3),
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001285 SENSOR_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4),
1286 SENSOR_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5),
1287 SENSOR_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6),
1288 SENSOR_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7),
1289 SENSOR_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8),
Guenter Roeckd36cf322011-02-07 15:08:54 -08001290};
1291
1292static struct sensor_device_attribute sda_temp_label[] = {
1293 SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
1294 SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
1295 SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
1296 SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001297 SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
1298 SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
1299 SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
1300 SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
1301 SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
Gong Juna157d062009-03-30 21:46:43 +02001302};
1303
1304static struct sensor_device_attribute sda_temp_max[] = {
Guenter Roeckbce26c52011-02-04 12:54:14 -08001305 SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max,
Yuan Mu412fec82006-02-05 23:24:16 +01001306 store_temp_max, 0),
Guenter Roeckbce26c52011-02-04 12:54:14 -08001307 SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
Yuan Mu412fec82006-02-05 23:24:16 +01001308 store_temp_max, 1),
Guenter Roeckbce26c52011-02-04 12:54:14 -08001309 SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
1310 store_temp_max, 2),
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001311 SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max,
1312 store_temp_max, 3),
1313 SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, show_temp_max,
1314 store_temp_max, 4),
1315 SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, show_temp_max,
1316 store_temp_max, 5),
1317 SENSOR_ATTR(temp7_max, S_IRUGO | S_IWUSR, show_temp_max,
1318 store_temp_max, 6),
1319 SENSOR_ATTR(temp8_max, S_IRUGO | S_IWUSR, show_temp_max,
1320 store_temp_max, 7),
1321 SENSOR_ATTR(temp9_max, S_IRUGO | S_IWUSR, show_temp_max,
1322 store_temp_max, 8),
Gong Juna157d062009-03-30 21:46:43 +02001323};
1324
1325static struct sensor_device_attribute sda_temp_max_hyst[] = {
Guenter Roeckbce26c52011-02-04 12:54:14 -08001326 SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
Yuan Mu412fec82006-02-05 23:24:16 +01001327 store_temp_max_hyst, 0),
Guenter Roeckbce26c52011-02-04 12:54:14 -08001328 SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
Yuan Mu412fec82006-02-05 23:24:16 +01001329 store_temp_max_hyst, 1),
Guenter Roeckbce26c52011-02-04 12:54:14 -08001330 SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1331 store_temp_max_hyst, 2),
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001332 SENSOR_ATTR(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1333 store_temp_max_hyst, 3),
1334 SENSOR_ATTR(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1335 store_temp_max_hyst, 4),
1336 SENSOR_ATTR(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1337 store_temp_max_hyst, 5),
1338 SENSOR_ATTR(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1339 store_temp_max_hyst, 6),
1340 SENSOR_ATTR(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1341 store_temp_max_hyst, 7),
1342 SENSOR_ATTR(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
1343 store_temp_max_hyst, 8),
Gong Juna157d062009-03-30 21:46:43 +02001344};
1345
1346static struct sensor_device_attribute sda_temp_alarm[] = {
Jean Delvarea4589db2006-03-23 16:30:29 +01001347 SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
1348 SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
1349 SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
Gong Juna157d062009-03-30 21:46:43 +02001350};
1351
1352static struct sensor_device_attribute sda_temp_type[] = {
Jean Delvareda667362007-06-24 11:21:02 +02001353 SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
1354 SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
1355 SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
Yuan Mu412fec82006-02-05 23:24:16 +01001356};
Jean Delvare08e7e272005-04-25 22:43:25 +02001357
Guenter Roeck840e1912012-02-08 09:29:11 -08001358static struct sensor_device_attribute sda_temp_offset[] = {
1359 SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1360 store_temp_offset, 0),
1361 SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1362 store_temp_offset, 1),
1363 SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1364 store_temp_offset, 2),
1365};
1366
Rudolf Marek08c79952006-07-05 18:14:31 +02001367#define show_pwm_reg(reg) \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001368static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1369 char *buf) \
Rudolf Marek08c79952006-07-05 18:14:31 +02001370{ \
1371 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001372 struct sensor_device_attribute *sensor_attr = \
1373 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001374 int nr = sensor_attr->index; \
1375 return sprintf(buf, "%d\n", data->reg[nr]); \
1376}
1377
1378show_pwm_reg(pwm_mode)
1379show_pwm_reg(pwm_enable)
1380show_pwm_reg(pwm)
1381
1382static ssize_t
1383store_pwm_mode(struct device *dev, struct device_attribute *attr,
1384 const char *buf, size_t count)
1385{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001386 struct w83627ehf_data *data = dev_get_drvdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001387 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09001388 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001389 int nr = sensor_attr->index;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001390 unsigned long val;
1391 int err;
Rudolf Marek08c79952006-07-05 18:14:31 +02001392 u16 reg;
1393
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001394 err = kstrtoul(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001395 if (err < 0)
1396 return err;
1397
Rudolf Marek08c79952006-07-05 18:14:31 +02001398 if (val > 1)
1399 return -EINVAL;
Guenter Roeckad77c3e2012-01-27 17:56:06 -08001400
1401 /* On NCT67766F, DC mode is only supported for pwm1 */
1402 if (sio_data->kind == nct6776 && nr && val != 1)
1403 return -EINVAL;
1404
Rudolf Marek08c79952006-07-05 18:14:31 +02001405 mutex_lock(&data->update_lock);
David Hubbard1ea6dd32007-06-24 11:16:15 +02001406 reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
Rudolf Marek08c79952006-07-05 18:14:31 +02001407 data->pwm_mode[nr] = val;
1408 reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
1409 if (!val)
1410 reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
David Hubbard1ea6dd32007-06-24 11:16:15 +02001411 w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
Rudolf Marek08c79952006-07-05 18:14:31 +02001412 mutex_unlock(&data->update_lock);
1413 return count;
1414}
1415
1416static ssize_t
1417store_pwm(struct device *dev, struct device_attribute *attr,
1418 const char *buf, size_t count)
1419{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001420 struct w83627ehf_data *data = dev_get_drvdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001421 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1422 int nr = sensor_attr->index;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001423 unsigned long val;
1424 int err;
1425
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001426 err = kstrtoul(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001427 if (err < 0)
1428 return err;
1429
Guenter Roeck2a844c12013-01-09 08:09:34 -08001430 val = clamp_val(val, 0, 255);
Rudolf Marek08c79952006-07-05 18:14:31 +02001431
1432 mutex_lock(&data->update_lock);
1433 data->pwm[nr] = val;
Guenter Roeck279af1a2011-02-13 22:34:47 -08001434 w83627ehf_write_value(data, data->REG_PWM[nr], val);
Rudolf Marek08c79952006-07-05 18:14:31 +02001435 mutex_unlock(&data->update_lock);
1436 return count;
1437}
1438
1439static ssize_t
1440store_pwm_enable(struct device *dev, struct device_attribute *attr,
1441 const char *buf, size_t count)
1442{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001443 struct w83627ehf_data *data = dev_get_drvdata(dev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09001444 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001445 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1446 int nr = sensor_attr->index;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001447 unsigned long val;
1448 int err;
Rudolf Marek08c79952006-07-05 18:14:31 +02001449 u16 reg;
1450
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001451 err = kstrtoul(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001452 if (err < 0)
1453 return err;
1454
Guenter Roeckb84bb512011-02-13 23:01:25 -08001455 if (!val || (val > 4 && val != data->pwm_enable_orig[nr]))
Rudolf Marek08c79952006-07-05 18:14:31 +02001456 return -EINVAL;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001457 /* SmartFan III mode is not supported on NCT6776F */
1458 if (sio_data->kind == nct6776 && val == 4)
1459 return -EINVAL;
1460
Rudolf Marek08c79952006-07-05 18:14:31 +02001461 mutex_lock(&data->update_lock);
Rudolf Marek08c79952006-07-05 18:14:31 +02001462 data->pwm_enable[nr] = val;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001463 if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
1464 reg = w83627ehf_read_value(data,
1465 NCT6775_REG_FAN_MODE[nr]);
1466 reg &= 0x0f;
1467 reg |= (val - 1) << 4;
1468 w83627ehf_write_value(data,
1469 NCT6775_REG_FAN_MODE[nr], reg);
1470 } else {
1471 reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
1472 reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
1473 reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
1474 w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
1475 }
Rudolf Marek08c79952006-07-05 18:14:31 +02001476 mutex_unlock(&data->update_lock);
1477 return count;
1478}
1479
1480
1481#define show_tol_temp(reg) \
1482static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1483 char *buf) \
1484{ \
1485 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001486 struct sensor_device_attribute *sensor_attr = \
1487 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001488 int nr = sensor_attr->index; \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001489 return sprintf(buf, "%d\n", data->reg[nr] * 1000); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001490}
1491
1492show_tol_temp(tolerance)
1493show_tol_temp(target_temp)
1494
1495static ssize_t
1496store_target_temp(struct device *dev, struct device_attribute *attr,
1497 const char *buf, size_t count)
1498{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001499 struct w83627ehf_data *data = dev_get_drvdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001500 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1501 int nr = sensor_attr->index;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001502 long val;
1503 int err;
1504
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001505 err = kstrtol(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001506 if (err < 0)
1507 return err;
1508
Guenter Roeck2a844c12013-01-09 08:09:34 -08001509 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
Rudolf Marek08c79952006-07-05 18:14:31 +02001510
1511 mutex_lock(&data->update_lock);
1512 data->target_temp[nr] = val;
Guenter Roeck279af1a2011-02-13 22:34:47 -08001513 w83627ehf_write_value(data, data->REG_TARGET[nr], val);
Rudolf Marek08c79952006-07-05 18:14:31 +02001514 mutex_unlock(&data->update_lock);
1515 return count;
1516}
1517
1518static ssize_t
1519store_tolerance(struct device *dev, struct device_attribute *attr,
1520 const char *buf, size_t count)
1521{
David Hubbard1ea6dd32007-06-24 11:16:15 +02001522 struct w83627ehf_data *data = dev_get_drvdata(dev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09001523 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Rudolf Marek08c79952006-07-05 18:14:31 +02001524 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1525 int nr = sensor_attr->index;
1526 u16 reg;
Guenter Roeckbce26c52011-02-04 12:54:14 -08001527 long val;
1528 int err;
1529
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001530 err = kstrtol(buf, 10, &val);
Guenter Roeckbce26c52011-02-04 12:54:14 -08001531 if (err < 0)
1532 return err;
1533
Rudolf Marek08c79952006-07-05 18:14:31 +02001534 /* Limit the temp to 0C - 15C */
Guenter Roeck2a844c12013-01-09 08:09:34 -08001535 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
Rudolf Marek08c79952006-07-05 18:14:31 +02001536
1537 mutex_lock(&data->update_lock);
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001538 if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
1539 /* Limit tolerance further for NCT6776F */
1540 if (sio_data->kind == nct6776 && val > 7)
1541 val = 7;
1542 reg = w83627ehf_read_value(data, NCT6775_REG_FAN_MODE[nr]);
Rudolf Marek08c79952006-07-05 18:14:31 +02001543 reg = (reg & 0xf0) | val;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001544 w83627ehf_write_value(data, NCT6775_REG_FAN_MODE[nr], reg);
1545 } else {
1546 reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
1547 if (nr == 1)
1548 reg = (reg & 0x0f) | (val << 4);
1549 else
1550 reg = (reg & 0xf0) | val;
1551 w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
1552 }
1553 data->tolerance[nr] = val;
Rudolf Marek08c79952006-07-05 18:14:31 +02001554 mutex_unlock(&data->update_lock);
1555 return count;
1556}
1557
1558static struct sensor_device_attribute sda_pwm[] = {
1559 SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
1560 SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
1561 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
1562 SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
1563};
1564
1565static struct sensor_device_attribute sda_pwm_mode[] = {
1566 SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1567 store_pwm_mode, 0),
1568 SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1569 store_pwm_mode, 1),
1570 SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1571 store_pwm_mode, 2),
1572 SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
1573 store_pwm_mode, 3),
1574};
1575
1576static struct sensor_device_attribute sda_pwm_enable[] = {
1577 SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1578 store_pwm_enable, 0),
1579 SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1580 store_pwm_enable, 1),
1581 SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1582 store_pwm_enable, 2),
1583 SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
1584 store_pwm_enable, 3),
1585};
1586
1587static struct sensor_device_attribute sda_target_temp[] = {
1588 SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
1589 store_target_temp, 0),
1590 SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
1591 store_target_temp, 1),
1592 SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
1593 store_target_temp, 2),
1594 SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
1595 store_target_temp, 3),
1596};
1597
1598static struct sensor_device_attribute sda_tolerance[] = {
1599 SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1600 store_tolerance, 0),
1601 SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1602 store_tolerance, 1),
1603 SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1604 store_tolerance, 2),
1605 SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
1606 store_tolerance, 3),
1607};
1608
Rudolf Marek08c79952006-07-05 18:14:31 +02001609/* Smart Fan registers */
1610
1611#define fan_functions(reg, REG) \
1612static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1613 char *buf) \
1614{ \
1615 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001616 struct sensor_device_attribute *sensor_attr = \
1617 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001618 int nr = sensor_attr->index; \
1619 return sprintf(buf, "%d\n", data->reg[nr]); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001620} \
Rudolf Marek08c79952006-07-05 18:14:31 +02001621static ssize_t \
1622store_##reg(struct device *dev, struct device_attribute *attr, \
1623 const char *buf, size_t count) \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001624{ \
David Hubbard1ea6dd32007-06-24 11:16:15 +02001625 struct w83627ehf_data *data = dev_get_drvdata(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001626 struct sensor_device_attribute *sensor_attr = \
1627 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001628 int nr = sensor_attr->index; \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001629 unsigned long val; \
1630 int err; \
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001631 err = kstrtoul(buf, 10, &val); \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001632 if (err < 0) \
1633 return err; \
Guenter Roeck2a844c12013-01-09 08:09:34 -08001634 val = clamp_val(val, 1, 255); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001635 mutex_lock(&data->update_lock); \
1636 data->reg[nr] = val; \
Guenter Roeckda2e0252010-08-14 21:08:55 +02001637 w83627ehf_write_value(data, data->REG_##REG[nr], val); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001638 mutex_unlock(&data->update_lock); \
1639 return count; \
1640}
1641
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001642fan_functions(fan_start_output, FAN_START_OUTPUT)
1643fan_functions(fan_stop_output, FAN_STOP_OUTPUT)
1644fan_functions(fan_max_output, FAN_MAX_OUTPUT)
1645fan_functions(fan_step_output, FAN_STEP_OUTPUT)
Rudolf Marek08c79952006-07-05 18:14:31 +02001646
1647#define fan_time_functions(reg, REG) \
1648static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
1649 char *buf) \
1650{ \
1651 struct w83627ehf_data *data = w83627ehf_update_device(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001652 struct sensor_device_attribute *sensor_attr = \
1653 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001654 int nr = sensor_attr->index; \
1655 return sprintf(buf, "%d\n", \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001656 step_time_from_reg(data->reg[nr], \
1657 data->pwm_mode[nr])); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001658} \
1659\
1660static ssize_t \
1661store_##reg(struct device *dev, struct device_attribute *attr, \
1662 const char *buf, size_t count) \
1663{ \
David Hubbard1ea6dd32007-06-24 11:16:15 +02001664 struct w83627ehf_data *data = dev_get_drvdata(dev); \
Guenter Roecke7e1ca62011-02-04 13:24:30 -08001665 struct sensor_device_attribute *sensor_attr = \
1666 to_sensor_dev_attr(attr); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001667 int nr = sensor_attr->index; \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001668 unsigned long val; \
1669 int err; \
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001670 err = kstrtoul(buf, 10, &val); \
Guenter Roeckbce26c52011-02-04 12:54:14 -08001671 if (err < 0) \
1672 return err; \
1673 val = step_time_to_reg(val, data->pwm_mode[nr]); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001674 mutex_lock(&data->update_lock); \
1675 data->reg[nr] = val; \
Guenter Roeck33fa9b62012-03-12 08:21:16 -07001676 w83627ehf_write_value(data, data->REG_##REG[nr], val); \
Rudolf Marek08c79952006-07-05 18:14:31 +02001677 mutex_unlock(&data->update_lock); \
1678 return count; \
1679} \
1680
1681fan_time_functions(fan_stop_time, FAN_STOP_TIME)
1682
Julia Lawall9bbacbf2016-12-22 13:05:10 +01001683static ssize_t name_show(struct device *dev, struct device_attribute *attr,
David Hubbard1ea6dd32007-06-24 11:16:15 +02001684 char *buf)
1685{
1686 struct w83627ehf_data *data = dev_get_drvdata(dev);
1687
1688 return sprintf(buf, "%s\n", data->name);
1689}
Julia Lawall9bbacbf2016-12-22 13:05:10 +01001690static DEVICE_ATTR_RO(name);
Rudolf Marek08c79952006-07-05 18:14:31 +02001691
1692static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
1693 SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1694 store_fan_stop_time, 3),
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001695 SENSOR_ATTR(pwm4_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1696 store_fan_start_output, 3),
1697 SENSOR_ATTR(pwm4_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1698 store_fan_stop_output, 3),
1699 SENSOR_ATTR(pwm4_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1700 store_fan_max_output, 3),
1701 SENSOR_ATTR(pwm4_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1702 store_fan_step_output, 3),
Rudolf Marek08c79952006-07-05 18:14:31 +02001703};
1704
Jean Delvareeff76872011-11-04 12:00:48 +01001705static struct sensor_device_attribute sda_sf3_arrays_fan3[] = {
1706 SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1707 store_fan_stop_time, 2),
1708 SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1709 store_fan_start_output, 2),
1710 SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1711 store_fan_stop_output, 2),
1712};
1713
Rudolf Marek08c79952006-07-05 18:14:31 +02001714static struct sensor_device_attribute sda_sf3_arrays[] = {
1715 SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1716 store_fan_stop_time, 0),
1717 SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1718 store_fan_stop_time, 1),
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001719 SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1720 store_fan_start_output, 0),
1721 SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1722 store_fan_start_output, 1),
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001723 SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1724 store_fan_stop_output, 0),
1725 SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1726 store_fan_stop_output, 1),
Guenter Roeckda2e0252010-08-14 21:08:55 +02001727};
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001728
Guenter Roeckda2e0252010-08-14 21:08:55 +02001729
1730/*
1731 * pwm1 and pwm3 don't support max and step settings on all chips.
1732 * Need to check support while generating/removing attribute files.
1733 */
1734static struct sensor_device_attribute sda_sf3_max_step_arrays[] = {
1735 SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1736 store_fan_max_output, 0),
1737 SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1738 store_fan_step_output, 0),
Daniel J Blueman41e9a062009-12-14 18:01:37 -08001739 SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1740 store_fan_max_output, 1),
1741 SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1742 store_fan_step_output, 1),
Guenter Roeckda2e0252010-08-14 21:08:55 +02001743 SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1744 store_fan_max_output, 2),
1745 SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1746 store_fan_step_output, 2),
Rudolf Marek08c79952006-07-05 18:14:31 +02001747};
1748
Jean Delvarefc18d6c2007-06-24 11:19:42 +02001749static ssize_t
Julia Lawall9bbacbf2016-12-22 13:05:10 +01001750cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf)
Jean Delvarefc18d6c2007-06-24 11:19:42 +02001751{
1752 struct w83627ehf_data *data = dev_get_drvdata(dev);
1753 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
1754}
Julia Lawall9bbacbf2016-12-22 13:05:10 +01001755static DEVICE_ATTR_RO(cpu0_vid);
Jean Delvarefc18d6c2007-06-24 11:19:42 +02001756
Dmitry Artamonow363a12a2011-08-12 16:41:11 -04001757
1758/* Case open detection */
1759
1760static ssize_t
1761show_caseopen(struct device *dev, struct device_attribute *attr, char *buf)
1762{
1763 struct w83627ehf_data *data = w83627ehf_update_device(dev);
1764
1765 return sprintf(buf, "%d\n",
1766 !!(data->caseopen & to_sensor_dev_attr_2(attr)->index));
1767}
1768
1769static ssize_t
1770clear_caseopen(struct device *dev, struct device_attribute *attr,
1771 const char *buf, size_t count)
1772{
1773 struct w83627ehf_data *data = dev_get_drvdata(dev);
1774 unsigned long val;
1775 u16 reg, mask;
1776
Frans Meulenbroeks179c4fd2012-01-04 20:58:52 +01001777 if (kstrtoul(buf, 10, &val) || val != 0)
Dmitry Artamonow363a12a2011-08-12 16:41:11 -04001778 return -EINVAL;
1779
1780 mask = to_sensor_dev_attr_2(attr)->nr;
1781
1782 mutex_lock(&data->update_lock);
1783 reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR);
1784 w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask);
1785 w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask);
1786 data->valid = 0; /* Force cache refresh */
1787 mutex_unlock(&data->update_lock);
1788
1789 return count;
1790}
1791
1792static struct sensor_device_attribute_2 sda_caseopen[] = {
1793 SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen,
1794 clear_caseopen, 0x80, 0x10),
1795 SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen,
1796 clear_caseopen, 0x40, 0x40),
1797};
1798
Jean Delvare08e7e272005-04-25 22:43:25 +02001799/*
David Hubbard1ea6dd32007-06-24 11:16:15 +02001800 * Driver and device management
Jean Delvare08e7e272005-04-25 22:43:25 +02001801 */
1802
David Hubbardc18beb52006-09-24 21:04:38 +02001803static void w83627ehf_device_remove_files(struct device *dev)
1804{
Guenter Roeck8969e842012-01-19 11:02:27 -08001805 /*
1806 * some entries in the following arrays may not have been used in
1807 * device_create_file(), but device_remove_file() will ignore them
1808 */
David Hubbardc18beb52006-09-24 21:04:38 +02001809 int i;
David Hubbard1ea6dd32007-06-24 11:16:15 +02001810 struct w83627ehf_data *data = dev_get_drvdata(dev);
David Hubbardc18beb52006-09-24 21:04:38 +02001811
1812 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
1813 device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
Guenter Roeckda2e0252010-08-14 21:08:55 +02001814 for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
1815 struct sensor_device_attribute *attr =
1816 &sda_sf3_max_step_arrays[i];
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001817 if (data->REG_FAN_STEP_OUTPUT &&
1818 data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
Guenter Roeckda2e0252010-08-14 21:08:55 +02001819 device_remove_file(dev, &attr->dev_attr);
1820 }
Jean Delvareeff76872011-11-04 12:00:48 +01001821 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++)
1822 device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr);
David Hubbardc18beb52006-09-24 21:04:38 +02001823 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
1824 device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
David Hubbard1ea6dd32007-06-24 11:16:15 +02001825 for (i = 0; i < data->in_num; i++) {
Gong Juna157d062009-03-30 21:46:43 +02001826 if ((i == 6) && data->in6_skip)
1827 continue;
David Hubbardc18beb52006-09-24 21:04:38 +02001828 device_remove_file(dev, &sda_in_input[i].dev_attr);
1829 device_remove_file(dev, &sda_in_alarm[i].dev_attr);
1830 device_remove_file(dev, &sda_in_min[i].dev_attr);
1831 device_remove_file(dev, &sda_in_max[i].dev_attr);
1832 }
1833 for (i = 0; i < 5; i++) {
1834 device_remove_file(dev, &sda_fan_input[i].dev_attr);
1835 device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
1836 device_remove_file(dev, &sda_fan_div[i].dev_attr);
1837 device_remove_file(dev, &sda_fan_min[i].dev_attr);
1838 }
Gong Jun237c8d2f2009-03-30 21:46:42 +02001839 for (i = 0; i < data->pwm_num; i++) {
David Hubbardc18beb52006-09-24 21:04:38 +02001840 device_remove_file(dev, &sda_pwm[i].dev_attr);
1841 device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
1842 device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
1843 device_remove_file(dev, &sda_target_temp[i].dev_attr);
1844 device_remove_file(dev, &sda_tolerance[i].dev_attr);
1845 }
Guenter Roeckd36cf322011-02-07 15:08:54 -08001846 for (i = 0; i < NUM_REG_TEMP; i++) {
1847 if (!(data->have_temp & (1 << i)))
Gong Juna157d062009-03-30 21:46:43 +02001848 continue;
1849 device_remove_file(dev, &sda_temp_input[i].dev_attr);
Guenter Roeckd36cf322011-02-07 15:08:54 -08001850 device_remove_file(dev, &sda_temp_label[i].dev_attr);
Jean Delvareeff76872011-11-04 12:00:48 +01001851 if (i == 2 && data->temp3_val_only)
1852 continue;
Gong Juna157d062009-03-30 21:46:43 +02001853 device_remove_file(dev, &sda_temp_max[i].dev_attr);
1854 device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001855 if (i > 2)
1856 continue;
Gong Juna157d062009-03-30 21:46:43 +02001857 device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
1858 device_remove_file(dev, &sda_temp_type[i].dev_attr);
Guenter Roeck840e1912012-02-08 09:29:11 -08001859 device_remove_file(dev, &sda_temp_offset[i].dev_attr);
Gong Juna157d062009-03-30 21:46:43 +02001860 }
David Hubbard1ea6dd32007-06-24 11:16:15 +02001861
Dmitry Artamonow363a12a2011-08-12 16:41:11 -04001862 device_remove_file(dev, &sda_caseopen[0].dev_attr);
1863 device_remove_file(dev, &sda_caseopen[1].dev_attr);
1864
David Hubbard1ea6dd32007-06-24 11:16:15 +02001865 device_remove_file(dev, &dev_attr_name);
Jean Delvarecbe311f2008-01-03 21:22:44 +01001866 device_remove_file(dev, &dev_attr_cpu0_vid);
David Hubbardc18beb52006-09-24 21:04:38 +02001867}
1868
David Hubbard1ea6dd32007-06-24 11:16:15 +02001869/* Get the monitoring functions started */
Bill Pemberton6c931ae2012-11-19 13:22:35 -05001870static inline void w83627ehf_init_device(struct w83627ehf_data *data,
Jean Delvarebf164c52011-10-13 15:49:08 -04001871 enum kinds kind)
Jean Delvare08e7e272005-04-25 22:43:25 +02001872{
1873 int i;
Jean Delvareda667362007-06-24 11:21:02 +02001874 u8 tmp, diode;
Jean Delvare08e7e272005-04-25 22:43:25 +02001875
1876 /* Start monitoring is needed */
David Hubbard1ea6dd32007-06-24 11:16:15 +02001877 tmp = w83627ehf_read_value(data, W83627EHF_REG_CONFIG);
Jean Delvare08e7e272005-04-25 22:43:25 +02001878 if (!(tmp & 0x01))
David Hubbard1ea6dd32007-06-24 11:16:15 +02001879 w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
Jean Delvare08e7e272005-04-25 22:43:25 +02001880 tmp | 0x01);
1881
Guenter Roeckd36cf322011-02-07 15:08:54 -08001882 /* Enable temperature sensors if needed */
1883 for (i = 0; i < NUM_REG_TEMP; i++) {
1884 if (!(data->have_temp & (1 << i)))
1885 continue;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001886 if (!data->reg_temp_config[i])
Guenter Roeckd36cf322011-02-07 15:08:54 -08001887 continue;
David Hubbard1ea6dd32007-06-24 11:16:15 +02001888 tmp = w83627ehf_read_value(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001889 data->reg_temp_config[i]);
Jean Delvare08e7e272005-04-25 22:43:25 +02001890 if (tmp & 0x01)
David Hubbard1ea6dd32007-06-24 11:16:15 +02001891 w83627ehf_write_value(data,
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001892 data->reg_temp_config[i],
Jean Delvare08e7e272005-04-25 22:43:25 +02001893 tmp & 0xfe);
1894 }
Jean Delvared3130f02007-06-24 11:20:13 +02001895
1896 /* Enable VBAT monitoring if needed */
1897 tmp = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
1898 if (!(tmp & 0x01))
1899 w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01);
Jean Delvareda667362007-06-24 11:21:02 +02001900
1901 /* Get thermal sensor types */
Jean Delvarebf164c52011-10-13 15:49:08 -04001902 switch (kind) {
1903 case w83627ehf:
1904 diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
1905 break;
Jean Delvareeff76872011-11-04 12:00:48 +01001906 case w83627uhg:
1907 diode = 0x00;
1908 break;
Jean Delvarebf164c52011-10-13 15:49:08 -04001909 default:
1910 diode = 0x70;
1911 }
Jean Delvareda667362007-06-24 11:21:02 +02001912 for (i = 0; i < 3; i++) {
Guenter Roeckbfa02b02011-11-06 20:25:18 +01001913 const char *label = NULL;
1914
1915 if (data->temp_label)
1916 label = data->temp_label[data->temp_src[i]];
Jean Delvare2265cef2011-11-04 12:00:47 +01001917
1918 /* Digital source overrides analog type */
Guenter Roeckbfa02b02011-11-06 20:25:18 +01001919 if (label && strncmp(label, "PECI", 4) == 0)
Jean Delvare2265cef2011-11-04 12:00:47 +01001920 data->temp_type[i] = 6;
Guenter Roeckbfa02b02011-11-06 20:25:18 +01001921 else if (label && strncmp(label, "AMD", 3) == 0)
Jean Delvare2265cef2011-11-04 12:00:47 +01001922 data->temp_type[i] = 5;
1923 else if ((tmp & (0x02 << i)))
Jean Delvarebf164c52011-10-13 15:49:08 -04001924 data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3;
Jean Delvareda667362007-06-24 11:21:02 +02001925 else
1926 data->temp_type[i] = 4; /* thermistor */
1927 }
Jean Delvare08e7e272005-04-25 22:43:25 +02001928}
1929
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001930static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
1931 int r1, int r2)
1932{
Fabian Frederickffe3df52015-07-03 14:39:06 +02001933 swap(data->temp_src[r1], data->temp_src[r2]);
1934 swap(data->reg_temp[r1], data->reg_temp[r2]);
1935 swap(data->reg_temp_over[r1], data->reg_temp_over[r2]);
1936 swap(data->reg_temp_hyst[r1], data->reg_temp_hyst[r2]);
1937 swap(data->reg_temp_config[r1], data->reg_temp_config[r2]);
Guenter Roeckec3e5a162011-02-02 08:46:49 -08001938}
1939
Bill Pemberton6c931ae2012-11-19 13:22:35 -05001940static void
Jean Delvare6ba71de2011-11-04 12:00:47 +01001941w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
1942{
1943 int i;
1944
1945 for (i = 0; i < n_temp; i++) {
1946 data->reg_temp[i] = W83627EHF_REG_TEMP[i];
1947 data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
1948 data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
1949 data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
1950 }
1951}
1952
Bill Pemberton6c931ae2012-11-19 13:22:35 -05001953static void
Jean Delvare03f5de22011-10-13 10:43:14 -04001954w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
1955 struct w83627ehf_data *data)
1956{
1957 int fan3pin, fan4pin, fan4min, fan5pin, regval;
1958
Jean Delvareeff76872011-11-04 12:00:48 +01001959 /* The W83627UHG is simple, only two fan inputs, no config */
1960 if (sio_data->kind == w83627uhg) {
1961 data->has_fan = 0x03; /* fan1 and fan2 */
1962 data->has_fan_min = 0x03;
1963 return;
1964 }
1965
Jean Delvare03f5de22011-10-13 10:43:14 -04001966 /* fan4 and fan5 share some pins with the GPIO and serial flash */
1967 if (sio_data->kind == nct6775) {
1968 /* On NCT6775, fan4 shares pins with the fdc interface */
1969 fan3pin = 1;
1970 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
1971 fan4min = 0;
1972 fan5pin = 0;
1973 } else if (sio_data->kind == nct6776) {
Guenter Roeck585c0fd2012-01-27 05:43:59 -08001974 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
1975
1976 superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
1977 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
1978
1979 if (regval & 0x80)
1980 fan3pin = gpok;
1981 else
1982 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
1983
1984 if (regval & 0x40)
1985 fan4pin = gpok;
1986 else
1987 fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
1988
1989 if (regval & 0x20)
1990 fan5pin = gpok;
1991 else
1992 fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
1993
Jean Delvare03f5de22011-10-13 10:43:14 -04001994 fan4min = fan4pin;
1995 } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
1996 fan3pin = 1;
1997 fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
1998 fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
1999 fan4min = fan4pin;
2000 } else {
2001 fan3pin = 1;
2002 fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
2003 fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
2004 fan4min = fan4pin;
2005 }
2006
Jean Delvare03f5de22011-10-13 10:43:14 -04002007 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
2008 data->has_fan |= (fan3pin << 2);
2009 data->has_fan_min |= (fan3pin << 2);
2010
2011 if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
2012 /*
2013 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1
2014 * register
2015 */
2016 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
2017 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
2018 } else {
2019 /*
2020 * It looks like fan4 and fan5 pins can be alternatively used
2021 * as fan on/off switches, but fan5 control is write only :/
2022 * We assume that if the serial interface is disabled, designers
2023 * connected fan5 as input unless they are emitting log 1, which
2024 * is not the default.
2025 */
2026 regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
2027 if ((regval & (1 << 2)) && fan4pin) {
2028 data->has_fan |= (1 << 3);
2029 data->has_fan_min |= (1 << 3);
2030 }
2031 if (!(regval & (1 << 1)) && fan5pin) {
2032 data->has_fan |= (1 << 4);
2033 data->has_fan_min |= (1 << 4);
2034 }
2035 }
2036}
2037
Bill Pemberton6c931ae2012-11-19 13:22:35 -05002038static int w83627ehf_probe(struct platform_device *pdev)
Jean Delvare08e7e272005-04-25 22:43:25 +02002039{
David Hubbard1ea6dd32007-06-24 11:16:15 +02002040 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002041 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Jean Delvare08e7e272005-04-25 22:43:25 +02002042 struct w83627ehf_data *data;
David Hubbard1ea6dd32007-06-24 11:16:15 +02002043 struct resource *res;
Jean Delvare03f5de22011-10-13 10:43:14 -04002044 u8 en_vrm10;
Jean Delvare08e7e272005-04-25 22:43:25 +02002045 int i, err = 0;
2046
David Hubbard1ea6dd32007-06-24 11:16:15 +02002047 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
2048 if (!request_region(res->start, IOREGION_LENGTH, DRVNAME)) {
Jean Delvare08e7e272005-04-25 22:43:25 +02002049 err = -EBUSY;
David Hubbard1ea6dd32007-06-24 11:16:15 +02002050 dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
2051 (unsigned long)res->start,
2052 (unsigned long)res->start + IOREGION_LENGTH - 1);
Jean Delvare08e7e272005-04-25 22:43:25 +02002053 goto exit;
2054 }
2055
Guenter Roeck32260d92012-03-12 08:33:10 -07002056 data = devm_kzalloc(&pdev->dev, sizeof(struct w83627ehf_data),
2057 GFP_KERNEL);
Guenter Roecke7e1ca62011-02-04 13:24:30 -08002058 if (!data) {
Jean Delvare08e7e272005-04-25 22:43:25 +02002059 err = -ENOMEM;
2060 goto exit_release;
2061 }
Jean Delvare08e7e272005-04-25 22:43:25 +02002062
David Hubbard1ea6dd32007-06-24 11:16:15 +02002063 data->addr = res->start;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01002064 mutex_init(&data->lock);
Ingo Molnar9a61bf62006-01-18 23:19:26 +01002065 mutex_init(&data->update_lock);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002066 data->name = w83627ehf_device_names[sio_data->kind];
Jean Delvare3300fb42012-11-05 21:54:39 +01002067 data->bank = 0xff; /* Force initial bank selection */
David Hubbard1ea6dd32007-06-24 11:16:15 +02002068 platform_set_drvdata(pdev, data);
Jean Delvare08e7e272005-04-25 22:43:25 +02002069
Gong Jun237c8d2f2009-03-30 21:46:42 +02002070 /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
2071 data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
Jean Delvareeff76872011-11-04 12:00:48 +01002072 /* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */
2073 switch (sio_data->kind) {
2074 default:
2075 data->pwm_num = 4;
2076 break;
2077 case w83667hg:
2078 case w83667hg_b:
2079 case nct6775:
2080 case nct6776:
2081 data->pwm_num = 3;
2082 break;
2083 case w83627uhg:
2084 data->pwm_num = 2;
2085 break;
2086 }
Jean Delvare08e7e272005-04-25 22:43:25 +02002087
Jean Delvare6ba71de2011-11-04 12:00:47 +01002088 /* Default to 3 temperature inputs, code below will adjust as needed */
Guenter Roeckd36cf322011-02-07 15:08:54 -08002089 data->have_temp = 0x07;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002090
2091 /* Deal with temperature register setup first. */
2092 if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
2093 int mask = 0;
2094
2095 /*
2096 * Display temperature sensor output only if it monitors
2097 * a source other than one already reported. Always display
2098 * first three temperature registers, though.
2099 */
2100 for (i = 0; i < NUM_REG_TEMP; i++) {
2101 u8 src;
2102
2103 data->reg_temp[i] = NCT6775_REG_TEMP[i];
2104 data->reg_temp_over[i] = NCT6775_REG_TEMP_OVER[i];
2105 data->reg_temp_hyst[i] = NCT6775_REG_TEMP_HYST[i];
2106 data->reg_temp_config[i] = NCT6775_REG_TEMP_CONFIG[i];
2107
2108 src = w83627ehf_read_value(data,
2109 NCT6775_REG_TEMP_SOURCE[i]);
2110 src &= 0x1f;
2111 if (src && !(mask & (1 << src))) {
2112 data->have_temp |= 1 << i;
2113 mask |= 1 << src;
2114 }
2115
2116 data->temp_src[i] = src;
2117
2118 /*
2119 * Now do some register swapping if index 0..2 don't
2120 * point to SYSTIN(1), CPUIN(2), and AUXIN(3).
2121 * Idea is to have the first three attributes
2122 * report SYSTIN, CPUIN, and AUXIN if possible
2123 * without overriding the basic system configuration.
2124 */
2125 if (i > 0 && data->temp_src[0] != 1
2126 && data->temp_src[i] == 1)
2127 w82627ehf_swap_tempreg(data, 0, i);
2128 if (i > 1 && data->temp_src[1] != 2
2129 && data->temp_src[i] == 2)
2130 w82627ehf_swap_tempreg(data, 1, i);
2131 if (i > 2 && data->temp_src[2] != 3
2132 && data->temp_src[i] == 3)
2133 w82627ehf_swap_tempreg(data, 2, i);
2134 }
2135 if (sio_data->kind == nct6776) {
2136 /*
2137 * On NCT6776, AUXTIN and VIN3 pins are shared.
2138 * Only way to detect it is to check if AUXTIN is used
2139 * as a temperature source, and if that source is
2140 * enabled.
2141 *
2142 * If that is the case, disable in6, which reports VIN3.
2143 * Otherwise disable temp3.
2144 */
2145 if (data->temp_src[2] == 3) {
2146 u8 reg;
2147
2148 if (data->reg_temp_config[2])
2149 reg = w83627ehf_read_value(data,
2150 data->reg_temp_config[2]);
2151 else
2152 reg = 0; /* Assume AUXTIN is used */
2153
2154 if (reg & 0x01)
2155 data->have_temp &= ~(1 << 2);
2156 else
2157 data->in6_skip = 1;
2158 }
Guenter Roeck02309ad2011-03-10 15:47:14 -08002159 data->temp_label = nct6776_temp_label;
2160 } else {
2161 data->temp_label = nct6775_temp_label;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002162 }
Guenter Roeck840e1912012-02-08 09:29:11 -08002163 data->have_temp_offset = data->have_temp & 0x07;
2164 for (i = 0; i < 3; i++) {
2165 if (data->temp_src[i] > 3)
2166 data->have_temp_offset &= ~(1 << i);
2167 }
Guenter Roeckd36cf322011-02-07 15:08:54 -08002168 } else if (sio_data->kind == w83667hg_b) {
2169 u8 reg;
2170
Jean Delvare6ba71de2011-11-04 12:00:47 +01002171 w83627ehf_set_temp_reg_ehf(data, 4);
2172
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002173 /*
2174 * Temperature sources are selected with bank 0, registers 0x49
2175 * and 0x4a.
2176 */
Guenter Roeckd36cf322011-02-07 15:08:54 -08002177 reg = w83627ehf_read_value(data, 0x4a);
2178 data->temp_src[0] = reg >> 5;
2179 reg = w83627ehf_read_value(data, 0x49);
2180 data->temp_src[1] = reg & 0x07;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002181 data->temp_src[2] = (reg >> 4) & 0x07;
Guenter Roeckd36cf322011-02-07 15:08:54 -08002182
2183 /*
2184 * W83667HG-B has another temperature register at 0x7e.
2185 * The temperature source is selected with register 0x7d.
2186 * Support it if the source differs from already reported
2187 * sources.
2188 */
2189 reg = w83627ehf_read_value(data, 0x7d);
2190 reg &= 0x07;
2191 if (reg != data->temp_src[0] && reg != data->temp_src[1]
2192 && reg != data->temp_src[2]) {
2193 data->temp_src[3] = reg;
2194 data->have_temp |= 1 << 3;
2195 }
2196
2197 /*
2198 * Chip supports either AUXTIN or VIN3. Try to find out which
2199 * one.
2200 */
2201 reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
2202 if (data->temp_src[2] == 2 && (reg & 0x01))
2203 data->have_temp &= ~(1 << 2);
2204
2205 if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2)))
2206 || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3))))
2207 data->in6_skip = 1;
2208
2209 data->temp_label = w83667hg_b_temp_label;
Guenter Roeck840e1912012-02-08 09:29:11 -08002210 data->have_temp_offset = data->have_temp & 0x07;
2211 for (i = 0; i < 3; i++) {
2212 if (data->temp_src[i] > 2)
2213 data->have_temp_offset &= ~(1 << i);
2214 }
Jean Delvareeff76872011-11-04 12:00:48 +01002215 } else if (sio_data->kind == w83627uhg) {
2216 u8 reg;
2217
2218 w83627ehf_set_temp_reg_ehf(data, 3);
2219
2220 /*
Jean Delvareaacb6b02012-03-13 04:03:27 -04002221 * Temperature sources for temp2 and temp3 are selected with
Jean Delvareeff76872011-11-04 12:00:48 +01002222 * bank 0, registers 0x49 and 0x4a.
2223 */
2224 data->temp_src[0] = 0; /* SYSTIN */
2225 reg = w83627ehf_read_value(data, 0x49) & 0x07;
2226 /* Adjust to have the same mapping as other source registers */
2227 if (reg == 0)
Jean Delvareaacb6b02012-03-13 04:03:27 -04002228 data->temp_src[1] = 1;
Jean Delvareeff76872011-11-04 12:00:48 +01002229 else if (reg >= 2 && reg <= 5)
Jean Delvareaacb6b02012-03-13 04:03:27 -04002230 data->temp_src[1] = reg + 2;
Jean Delvareeff76872011-11-04 12:00:48 +01002231 else /* should never happen */
2232 data->have_temp &= ~(1 << 1);
2233 reg = w83627ehf_read_value(data, 0x4a);
2234 data->temp_src[2] = reg >> 5;
2235
2236 /*
2237 * Skip temp3 if source is invalid or the same as temp1
2238 * or temp2.
2239 */
2240 if (data->temp_src[2] == 2 || data->temp_src[2] == 3 ||
2241 data->temp_src[2] == data->temp_src[0] ||
2242 ((data->have_temp & (1 << 1)) &&
2243 data->temp_src[2] == data->temp_src[1]))
2244 data->have_temp &= ~(1 << 2);
2245 else
2246 data->temp3_val_only = 1; /* No limit regs */
2247
2248 data->in6_skip = 1; /* No VIN3 */
2249
2250 data->temp_label = w83667hg_b_temp_label;
Guenter Roeck840e1912012-02-08 09:29:11 -08002251 data->have_temp_offset = data->have_temp & 0x03;
2252 for (i = 0; i < 3; i++) {
2253 if (data->temp_src[i] > 1)
2254 data->have_temp_offset &= ~(1 << i);
2255 }
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002256 } else {
Jean Delvare6ba71de2011-11-04 12:00:47 +01002257 w83627ehf_set_temp_reg_ehf(data, 3);
2258
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002259 /* Temperature sources are fixed */
Jean Delvare6ba71de2011-11-04 12:00:47 +01002260
2261 if (sio_data->kind == w83667hg) {
2262 u8 reg;
2263
2264 /*
2265 * Chip supports either AUXTIN or VIN3. Try to find
2266 * out which one.
2267 */
2268 reg = w83627ehf_read_value(data,
2269 W83627EHF_REG_TEMP_CONFIG[2]);
2270 if (reg & 0x01)
2271 data->have_temp &= ~(1 << 2);
2272 else
2273 data->in6_skip = 1;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002274 }
Guenter Roeck840e1912012-02-08 09:29:11 -08002275 data->have_temp_offset = data->have_temp & 0x07;
Gong Juna157d062009-03-30 21:46:43 +02002276 }
2277
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002278 if (sio_data->kind == nct6775) {
Guenter Roeck26bc4402011-02-11 08:00:58 -08002279 data->has_fan_div = true;
2280 data->fan_from_reg = fan_from_reg16;
2281 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002282 data->REG_PWM = NCT6775_REG_PWM;
2283 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck26bc4402011-02-11 08:00:58 -08002284 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002285 data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
2286 data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
2287 data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
2288 data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
2289 data->REG_FAN_MAX_OUTPUT = NCT6775_REG_FAN_MAX_OUTPUT;
2290 data->REG_FAN_STEP_OUTPUT = NCT6775_REG_FAN_STEP_OUTPUT;
2291 } else if (sio_data->kind == nct6776) {
Guenter Roeck26bc4402011-02-11 08:00:58 -08002292 data->has_fan_div = false;
2293 data->fan_from_reg = fan_from_reg13;
2294 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002295 data->REG_PWM = NCT6775_REG_PWM;
2296 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck26bc4402011-02-11 08:00:58 -08002297 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002298 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
2299 data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
2300 data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
2301 data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
2302 } else if (sio_data->kind == w83667hg_b) {
Guenter Roeck26bc4402011-02-11 08:00:58 -08002303 data->has_fan_div = true;
2304 data->fan_from_reg = fan_from_reg8;
2305 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002306 data->REG_PWM = W83627EHF_REG_PWM;
2307 data->REG_TARGET = W83627EHF_REG_TARGET;
2308 data->REG_FAN = W83627EHF_REG_FAN;
2309 data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
2310 data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
2311 data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
2312 data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
Guenter Roeckc39aeda2010-08-14 21:08:55 +02002313 data->REG_FAN_MAX_OUTPUT =
2314 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B;
2315 data->REG_FAN_STEP_OUTPUT =
2316 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B;
2317 } else {
Guenter Roeck26bc4402011-02-11 08:00:58 -08002318 data->has_fan_div = true;
2319 data->fan_from_reg = fan_from_reg8;
2320 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002321 data->REG_PWM = W83627EHF_REG_PWM;
2322 data->REG_TARGET = W83627EHF_REG_TARGET;
2323 data->REG_FAN = W83627EHF_REG_FAN;
2324 data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
2325 data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
2326 data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
2327 data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
Guenter Roeckc39aeda2010-08-14 21:08:55 +02002328 data->REG_FAN_MAX_OUTPUT =
2329 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON;
2330 data->REG_FAN_STEP_OUTPUT =
2331 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
2332 }
Guenter Roeckda2e0252010-08-14 21:08:55 +02002333
Jean Delvareeff76872011-11-04 12:00:48 +01002334 /* Setup input voltage scaling factors */
2335 if (sio_data->kind == w83627uhg)
2336 data->scale_in = scale_in_w83627uhg;
2337 else
2338 data->scale_in = scale_in_common;
2339
Jean Delvare08e7e272005-04-25 22:43:25 +02002340 /* Initialize the chip */
Jean Delvarebf164c52011-10-13 15:49:08 -04002341 w83627ehf_init_device(data, sio_data->kind);
Jean Delvare08e7e272005-04-25 22:43:25 +02002342
Jean Delvarefc18d6c2007-06-24 11:19:42 +02002343 data->vrm = vid_which_vrm();
Katsumi Sato0d023532017-02-22 13:32:10 +09002344
2345 err = superio_enter(sio_data->sioreg);
2346 if (err)
2347 goto exit_release;
2348
Jean Delvarefc18d6c2007-06-24 11:19:42 +02002349 /* Read VID value */
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002350 if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b ||
2351 sio_data->kind == nct6775 || sio_data->kind == nct6776) {
Guenter Roeck8969e842012-01-19 11:02:27 -08002352 /*
2353 * W83667HG has different pins for VID input and output, so
2354 * we can get the VID input values directly at logical device D
2355 * 0xe3.
2356 */
Gong Jun237c8d2f2009-03-30 21:46:42 +02002357 superio_select(sio_data->sioreg, W83667HG_LD_VID);
2358 data->vid = superio_inb(sio_data->sioreg, 0xe3);
Jean Delvarecbe311f2008-01-03 21:22:44 +01002359 err = device_create_file(dev, &dev_attr_cpu0_vid);
Katsumi Sato0d023532017-02-22 13:32:10 +09002360 if (err) {
2361 superio_exit(sio_data->sioreg);
Jean Delvarecbe311f2008-01-03 21:22:44 +01002362 goto exit_release;
Katsumi Sato0d023532017-02-22 13:32:10 +09002363 }
Jean Delvareeff76872011-11-04 12:00:48 +01002364 } else if (sio_data->kind != w83627uhg) {
Gong Jun237c8d2f2009-03-30 21:46:42 +02002365 superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
2366 if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
Guenter Roeck8969e842012-01-19 11:02:27 -08002367 /*
2368 * Set VID input sensibility if needed. In theory the
2369 * BIOS should have set it, but in practice it's not
2370 * always the case. We only do it for the W83627EHF/EHG
2371 * because the W83627DHG is more complex in this
2372 * respect.
2373 */
Gong Jun237c8d2f2009-03-30 21:46:42 +02002374 if (sio_data->kind == w83627ehf) {
2375 en_vrm10 = superio_inb(sio_data->sioreg,
2376 SIO_REG_EN_VRM10);
2377 if ((en_vrm10 & 0x08) && data->vrm == 90) {
Guenter Roeckb55f3752013-01-10 10:01:24 -08002378 dev_warn(dev,
2379 "Setting VID input voltage to TTL\n");
Gong Jun237c8d2f2009-03-30 21:46:42 +02002380 superio_outb(sio_data->sioreg,
2381 SIO_REG_EN_VRM10,
2382 en_vrm10 & ~0x08);
2383 } else if (!(en_vrm10 & 0x08)
2384 && data->vrm == 100) {
Guenter Roeckb55f3752013-01-10 10:01:24 -08002385 dev_warn(dev,
2386 "Setting VID input voltage to VRM10\n");
Gong Jun237c8d2f2009-03-30 21:46:42 +02002387 superio_outb(sio_data->sioreg,
2388 SIO_REG_EN_VRM10,
2389 en_vrm10 | 0x08);
2390 }
2391 }
2392
2393 data->vid = superio_inb(sio_data->sioreg,
2394 SIO_REG_VID_DATA);
2395 if (sio_data->kind == w83627ehf) /* 6 VID pins only */
2396 data->vid &= 0x3f;
2397
2398 err = device_create_file(dev, &dev_attr_cpu0_vid);
Katsumi Sato0d023532017-02-22 13:32:10 +09002399 if (err) {
2400 superio_exit(sio_data->sioreg);
Gong Jun237c8d2f2009-03-30 21:46:42 +02002401 goto exit_release;
Katsumi Sato0d023532017-02-22 13:32:10 +09002402 }
Gong Jun237c8d2f2009-03-30 21:46:42 +02002403 } else {
Guenter Roeckb55f3752013-01-10 10:01:24 -08002404 dev_info(dev,
2405 "VID pins in output mode, CPU VID not available\n");
Gong Jun237c8d2f2009-03-30 21:46:42 +02002406 }
Jean Delvarefc18d6c2007-06-24 11:19:42 +02002407 }
2408
Ian Dobsond42e869a2011-03-07 14:21:12 -08002409 if (fan_debounce &&
2410 (sio_data->kind == nct6775 || sio_data->kind == nct6776)) {
2411 u8 tmp;
2412
2413 superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
2414 tmp = superio_inb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE);
2415 if (sio_data->kind == nct6776)
2416 superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
2417 0x3e | tmp);
2418 else
2419 superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
2420 0x1e | tmp);
2421 pr_info("Enabled fan debounce for chip %s\n", data->name);
2422 }
2423
Jean Delvare03f5de22011-10-13 10:43:14 -04002424 w83627ehf_check_fan_inputs(sio_data, data);
Jean Delvare08e7e272005-04-25 22:43:25 +02002425
Katsumi Sato0d023532017-02-22 13:32:10 +09002426 superio_exit(sio_data->sioreg);
2427
Mark M. Hoffmanea7be662007-08-05 12:19:01 -04002428 /* Read fan clock dividers immediately */
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002429 w83627ehf_update_fan_div_common(dev, data);
2430
2431 /* Read pwm data to save original values */
2432 w83627ehf_update_pwm_common(dev, data);
2433 for (i = 0; i < data->pwm_num; i++)
2434 data->pwm_enable_orig[i] = data->pwm_enable[i];
Mark M. Hoffmanea7be662007-08-05 12:19:01 -04002435
Jean Delvare08e7e272005-04-25 22:43:25 +02002436 /* Register sysfs hooks */
Guenter Roecke7e1ca62011-02-04 13:24:30 -08002437 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) {
2438 err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr);
2439 if (err)
David Hubbardc18beb52006-09-24 21:04:38 +02002440 goto exit_remove;
Guenter Roecke7e1ca62011-02-04 13:24:30 -08002441 }
Rudolf Marek08c79952006-07-05 18:14:31 +02002442
Guenter Roeckda2e0252010-08-14 21:08:55 +02002443 for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
2444 struct sensor_device_attribute *attr =
2445 &sda_sf3_max_step_arrays[i];
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002446 if (data->REG_FAN_STEP_OUTPUT &&
2447 data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
Guenter Roeckda2e0252010-08-14 21:08:55 +02002448 err = device_create_file(dev, &attr->dev_attr);
2449 if (err)
2450 goto exit_remove;
2451 }
2452 }
Jean Delvareeff76872011-11-04 12:00:48 +01002453 /* if fan3 and fan4 are enabled create the sf3 files for them */
2454 if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3)
2455 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) {
2456 err = device_create_file(dev,
2457 &sda_sf3_arrays_fan3[i].dev_attr);
2458 if (err)
2459 goto exit_remove;
2460 }
Gong Jun237c8d2f2009-03-30 21:46:42 +02002461 if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
David Hubbardc18beb52006-09-24 21:04:38 +02002462 for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
Guenter Roecke7e1ca62011-02-04 13:24:30 -08002463 err = device_create_file(dev,
2464 &sda_sf3_arrays_fan4[i].dev_attr);
2465 if (err)
David Hubbardc18beb52006-09-24 21:04:38 +02002466 goto exit_remove;
2467 }
Rudolf Marek08c79952006-07-05 18:14:31 +02002468
Gong Juna157d062009-03-30 21:46:43 +02002469 for (i = 0; i < data->in_num; i++) {
2470 if ((i == 6) && data->in6_skip)
2471 continue;
David Hubbardc18beb52006-09-24 21:04:38 +02002472 if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
2473 || (err = device_create_file(dev,
2474 &sda_in_alarm[i].dev_attr))
2475 || (err = device_create_file(dev,
2476 &sda_in_min[i].dev_attr))
2477 || (err = device_create_file(dev,
2478 &sda_in_max[i].dev_attr)))
2479 goto exit_remove;
Gong Juna157d062009-03-30 21:46:43 +02002480 }
Rudolf Marekcf0676f2006-03-23 16:25:22 +01002481
Yuan Mu412fec82006-02-05 23:24:16 +01002482 for (i = 0; i < 5; i++) {
Rudolf Marek08c79952006-07-05 18:14:31 +02002483 if (data->has_fan & (1 << i)) {
David Hubbardc18beb52006-09-24 21:04:38 +02002484 if ((err = device_create_file(dev,
2485 &sda_fan_input[i].dev_attr))
2486 || (err = device_create_file(dev,
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002487 &sda_fan_alarm[i].dev_attr)))
David Hubbardc18beb52006-09-24 21:04:38 +02002488 goto exit_remove;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002489 if (sio_data->kind != nct6776) {
2490 err = device_create_file(dev,
2491 &sda_fan_div[i].dev_attr);
2492 if (err)
2493 goto exit_remove;
2494 }
2495 if (data->has_fan_min & (1 << i)) {
2496 err = device_create_file(dev,
2497 &sda_fan_min[i].dev_attr);
2498 if (err)
2499 goto exit_remove;
2500 }
Gong Jun237c8d2f2009-03-30 21:46:42 +02002501 if (i < data->pwm_num &&
David Hubbardc18beb52006-09-24 21:04:38 +02002502 ((err = device_create_file(dev,
2503 &sda_pwm[i].dev_attr))
2504 || (err = device_create_file(dev,
2505 &sda_pwm_mode[i].dev_attr))
2506 || (err = device_create_file(dev,
2507 &sda_pwm_enable[i].dev_attr))
2508 || (err = device_create_file(dev,
2509 &sda_target_temp[i].dev_attr))
2510 || (err = device_create_file(dev,
2511 &sda_tolerance[i].dev_attr))))
2512 goto exit_remove;
Rudolf Marek08c79952006-07-05 18:14:31 +02002513 }
Jean Delvare08e7e272005-04-25 22:43:25 +02002514 }
Rudolf Marek08c79952006-07-05 18:14:31 +02002515
Guenter Roeckd36cf322011-02-07 15:08:54 -08002516 for (i = 0; i < NUM_REG_TEMP; i++) {
2517 if (!(data->have_temp & (1 << i)))
Gong Juna157d062009-03-30 21:46:43 +02002518 continue;
Guenter Roeckd36cf322011-02-07 15:08:54 -08002519 err = device_create_file(dev, &sda_temp_input[i].dev_attr);
2520 if (err)
2521 goto exit_remove;
2522 if (data->temp_label) {
2523 err = device_create_file(dev,
2524 &sda_temp_label[i].dev_attr);
2525 if (err)
2526 goto exit_remove;
2527 }
Jean Delvareeff76872011-11-04 12:00:48 +01002528 if (i == 2 && data->temp3_val_only)
2529 continue;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002530 if (data->reg_temp_over[i]) {
2531 err = device_create_file(dev,
2532 &sda_temp_max[i].dev_attr);
2533 if (err)
2534 goto exit_remove;
2535 }
2536 if (data->reg_temp_hyst[i]) {
2537 err = device_create_file(dev,
2538 &sda_temp_max_hyst[i].dev_attr);
2539 if (err)
2540 goto exit_remove;
2541 }
Guenter Roeckd36cf322011-02-07 15:08:54 -08002542 if (i > 2)
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002543 continue;
2544 if ((err = device_create_file(dev,
Gong Juna157d062009-03-30 21:46:43 +02002545 &sda_temp_alarm[i].dev_attr))
2546 || (err = device_create_file(dev,
2547 &sda_temp_type[i].dev_attr)))
David Hubbardc18beb52006-09-24 21:04:38 +02002548 goto exit_remove;
Guenter Roeck840e1912012-02-08 09:29:11 -08002549 if (data->have_temp_offset & (1 << i)) {
2550 err = device_create_file(dev,
2551 &sda_temp_offset[i].dev_attr);
2552 if (err)
2553 goto exit_remove;
2554 }
Gong Juna157d062009-03-30 21:46:43 +02002555 }
David Hubbardc18beb52006-09-24 21:04:38 +02002556
Dmitry Artamonow363a12a2011-08-12 16:41:11 -04002557 err = device_create_file(dev, &sda_caseopen[0].dev_attr);
2558 if (err)
2559 goto exit_remove;
2560
2561 if (sio_data->kind == nct6776) {
2562 err = device_create_file(dev, &sda_caseopen[1].dev_attr);
2563 if (err)
2564 goto exit_remove;
2565 }
2566
David Hubbard1ea6dd32007-06-24 11:16:15 +02002567 err = device_create_file(dev, &dev_attr_name);
2568 if (err)
2569 goto exit_remove;
2570
Tony Jones1beeffe2007-08-20 13:46:20 -07002571 data->hwmon_dev = hwmon_device_register(dev);
2572 if (IS_ERR(data->hwmon_dev)) {
2573 err = PTR_ERR(data->hwmon_dev);
David Hubbardc18beb52006-09-24 21:04:38 +02002574 goto exit_remove;
2575 }
Jean Delvare08e7e272005-04-25 22:43:25 +02002576
2577 return 0;
2578
David Hubbardc18beb52006-09-24 21:04:38 +02002579exit_remove:
2580 w83627ehf_device_remove_files(dev);
Jean Delvare08e7e272005-04-25 22:43:25 +02002581exit_release:
David Hubbard1ea6dd32007-06-24 11:16:15 +02002582 release_region(res->start, IOREGION_LENGTH);
Jean Delvare08e7e272005-04-25 22:43:25 +02002583exit:
2584 return err;
2585}
2586
Bill Pemberton281dfd02012-11-19 13:25:51 -05002587static int w83627ehf_remove(struct platform_device *pdev)
Jean Delvare08e7e272005-04-25 22:43:25 +02002588{
David Hubbard1ea6dd32007-06-24 11:16:15 +02002589 struct w83627ehf_data *data = platform_get_drvdata(pdev);
Jean Delvare08e7e272005-04-25 22:43:25 +02002590
Tony Jones1beeffe2007-08-20 13:46:20 -07002591 hwmon_device_unregister(data->hwmon_dev);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002592 w83627ehf_device_remove_files(&pdev->dev);
2593 release_region(data->addr, IOREGION_LENGTH);
Jean Delvare08e7e272005-04-25 22:43:25 +02002594
2595 return 0;
2596}
2597
Jean Delvare7e630bb2012-12-19 22:16:59 +01002598#ifdef CONFIG_PM
2599static int w83627ehf_suspend(struct device *dev)
2600{
2601 struct w83627ehf_data *data = w83627ehf_update_device(dev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002602 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Jean Delvare7e630bb2012-12-19 22:16:59 +01002603
2604 mutex_lock(&data->update_lock);
2605 data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
2606 if (sio_data->kind == nct6775) {
2607 data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
2608 data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
2609 }
2610 mutex_unlock(&data->update_lock);
2611
2612 return 0;
2613}
2614
2615static int w83627ehf_resume(struct device *dev)
2616{
2617 struct w83627ehf_data *data = dev_get_drvdata(dev);
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09002618 struct w83627ehf_sio_data *sio_data = dev_get_platdata(dev);
Jean Delvare7e630bb2012-12-19 22:16:59 +01002619 int i;
2620
2621 mutex_lock(&data->update_lock);
2622 data->bank = 0xff; /* Force initial bank selection */
2623
2624 /* Restore limits */
2625 for (i = 0; i < data->in_num; i++) {
2626 if ((i == 6) && data->in6_skip)
2627 continue;
2628
2629 w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i),
2630 data->in_min[i]);
2631 w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i),
2632 data->in_max[i]);
2633 }
2634
2635 for (i = 0; i < 5; i++) {
2636 if (!(data->has_fan_min & (1 << i)))
2637 continue;
2638
2639 w83627ehf_write_value(data, data->REG_FAN_MIN[i],
2640 data->fan_min[i]);
2641 }
2642
2643 for (i = 0; i < NUM_REG_TEMP; i++) {
2644 if (!(data->have_temp & (1 << i)))
2645 continue;
2646
2647 if (data->reg_temp_over[i])
2648 w83627ehf_write_temp(data, data->reg_temp_over[i],
2649 data->temp_max[i]);
2650 if (data->reg_temp_hyst[i])
2651 w83627ehf_write_temp(data, data->reg_temp_hyst[i],
2652 data->temp_max_hyst[i]);
Jean Delvare45633fb2012-12-19 22:17:00 +01002653 if (i > 2)
2654 continue;
Jean Delvare7e630bb2012-12-19 22:16:59 +01002655 if (data->have_temp_offset & (1 << i))
2656 w83627ehf_write_value(data,
2657 W83627EHF_REG_TEMP_OFFSET[i],
2658 data->temp_offset[i]);
2659 }
2660
2661 /* Restore other settings */
2662 w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
2663 if (sio_data->kind == nct6775) {
2664 w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
2665 w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
2666 }
2667
2668 /* Force re-reading all values */
2669 data->valid = 0;
2670 mutex_unlock(&data->update_lock);
2671
2672 return 0;
2673}
2674
2675static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
2676 .suspend = w83627ehf_suspend,
2677 .resume = w83627ehf_resume,
Harald Judte3b20b32013-08-01 16:18:45 +02002678 .freeze = w83627ehf_suspend,
2679 .restore = w83627ehf_resume,
Jean Delvare7e630bb2012-12-19 22:16:59 +01002680};
2681
2682#define W83627EHF_DEV_PM_OPS (&w83627ehf_dev_pm_ops)
2683#else
2684#define W83627EHF_DEV_PM_OPS NULL
2685#endif /* CONFIG_PM */
2686
David Hubbard1ea6dd32007-06-24 11:16:15 +02002687static struct platform_driver w83627ehf_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +01002688 .driver = {
David Hubbard1ea6dd32007-06-24 11:16:15 +02002689 .name = DRVNAME,
Jean Delvare7e630bb2012-12-19 22:16:59 +01002690 .pm = W83627EHF_DEV_PM_OPS,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01002691 },
David Hubbard1ea6dd32007-06-24 11:16:15 +02002692 .probe = w83627ehf_probe,
Bill Pemberton9e5e9b72012-11-19 13:21:20 -05002693 .remove = w83627ehf_remove,
Jean Delvare08e7e272005-04-25 22:43:25 +02002694};
2695
David Hubbard1ea6dd32007-06-24 11:16:15 +02002696/* w83627ehf_find() looks for a '627 in the Super-I/O config space */
2697static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
2698 struct w83627ehf_sio_data *sio_data)
Jean Delvare08e7e272005-04-25 22:43:25 +02002699{
Uwe Kleine-König6f7805a2012-03-30 16:04:55 -04002700 static const char sio_name_W83627EHF[] __initconst = "W83627EHF";
2701 static const char sio_name_W83627EHG[] __initconst = "W83627EHG";
2702 static const char sio_name_W83627DHG[] __initconst = "W83627DHG";
2703 static const char sio_name_W83627DHG_P[] __initconst = "W83627DHG-P";
2704 static const char sio_name_W83627UHG[] __initconst = "W83627UHG";
2705 static const char sio_name_W83667HG[] __initconst = "W83667HG";
2706 static const char sio_name_W83667HG_B[] __initconst = "W83667HG-B";
2707 static const char sio_name_NCT6775[] __initconst = "NCT6775F";
2708 static const char sio_name_NCT6776[] __initconst = "NCT6776F";
David Hubbard1ea6dd32007-06-24 11:16:15 +02002709
Jean Delvare08e7e272005-04-25 22:43:25 +02002710 u16 val;
David Hubbard1ea6dd32007-06-24 11:16:15 +02002711 const char *sio_name;
Katsumi Sato0d023532017-02-22 13:32:10 +09002712 int err;
Jean Delvare08e7e272005-04-25 22:43:25 +02002713
Katsumi Sato0d023532017-02-22 13:32:10 +09002714 err = superio_enter(sioaddr);
2715 if (err)
2716 return err;
Jean Delvare08e7e272005-04-25 22:43:25 +02002717
Jean Delvare67b671b2007-12-06 23:13:42 +01002718 if (force_id)
2719 val = force_id;
2720 else
2721 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
2722 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
David Hubbard657c93b2007-02-14 21:15:04 +01002723 switch (val & SIO_ID_MASK) {
David Hubbard657c93b2007-02-14 21:15:04 +01002724 case SIO_W83627EHF_ID:
David Hubbard1ea6dd32007-06-24 11:16:15 +02002725 sio_data->kind = w83627ehf;
2726 sio_name = sio_name_W83627EHF;
2727 break;
David Hubbard657c93b2007-02-14 21:15:04 +01002728 case SIO_W83627EHG_ID:
David Hubbard1ea6dd32007-06-24 11:16:15 +02002729 sio_data->kind = w83627ehf;
2730 sio_name = sio_name_W83627EHG;
2731 break;
2732 case SIO_W83627DHG_ID:
2733 sio_data->kind = w83627dhg;
2734 sio_name = sio_name_W83627DHG;
David Hubbard657c93b2007-02-14 21:15:04 +01002735 break;
Jean Delvarec1e48dc2009-06-15 18:39:50 +02002736 case SIO_W83627DHG_P_ID:
2737 sio_data->kind = w83627dhg_p;
2738 sio_name = sio_name_W83627DHG_P;
2739 break;
Jean Delvareeff76872011-11-04 12:00:48 +01002740 case SIO_W83627UHG_ID:
2741 sio_data->kind = w83627uhg;
2742 sio_name = sio_name_W83627UHG;
2743 break;
Gong Jun237c8d2f2009-03-30 21:46:42 +02002744 case SIO_W83667HG_ID:
2745 sio_data->kind = w83667hg;
2746 sio_name = sio_name_W83667HG;
2747 break;
Guenter Roeckc39aeda2010-08-14 21:08:55 +02002748 case SIO_W83667HG_B_ID:
2749 sio_data->kind = w83667hg_b;
2750 sio_name = sio_name_W83667HG_B;
2751 break;
Guenter Roeckec3e5a162011-02-02 08:46:49 -08002752 case SIO_NCT6775_ID:
2753 sio_data->kind = nct6775;
2754 sio_name = sio_name_NCT6775;
2755 break;
2756 case SIO_NCT6776_ID:
2757 sio_data->kind = nct6776;
2758 sio_name = sio_name_NCT6776;
2759 break;
David Hubbard657c93b2007-02-14 21:15:04 +01002760 default:
Jean Delvare9f660362007-06-24 11:23:41 +02002761 if (val != 0xffff)
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002762 pr_debug("unsupported chip ID: 0x%04x\n", val);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002763 superio_exit(sioaddr);
Jean Delvare08e7e272005-04-25 22:43:25 +02002764 return -ENODEV;
2765 }
2766
David Hubbard1ea6dd32007-06-24 11:16:15 +02002767 /* We have a known chip, find the HWM I/O address */
2768 superio_select(sioaddr, W83627EHF_LD_HWM);
2769 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
2770 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Jean Delvare1a641fc2007-04-23 14:41:16 -07002771 *addr = val & IOREGION_ALIGNMENT;
Jean Delvare2d8672c2005-07-19 23:56:35 +02002772 if (*addr == 0) {
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002773 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
David Hubbard1ea6dd32007-06-24 11:16:15 +02002774 superio_exit(sioaddr);
Jean Delvare08e7e272005-04-25 22:43:25 +02002775 return -ENODEV;
2776 }
2777
2778 /* Activate logical device if needed */
David Hubbard1ea6dd32007-06-24 11:16:15 +02002779 val = superio_inb(sioaddr, SIO_REG_ENABLE);
David Hubbard475ef852007-06-24 11:17:09 +02002780 if (!(val & 0x01)) {
Guenter Roeckb55f3752013-01-10 10:01:24 -08002781 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
David Hubbard1ea6dd32007-06-24 11:16:15 +02002782 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
David Hubbard475ef852007-06-24 11:17:09 +02002783 }
Jean Delvare08e7e272005-04-25 22:43:25 +02002784
David Hubbard1ea6dd32007-06-24 11:16:15 +02002785 superio_exit(sioaddr);
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002786 pr_info("Found %s chip at %#x\n", sio_name, *addr);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002787 sio_data->sioreg = sioaddr;
2788
Jean Delvare08e7e272005-04-25 22:43:25 +02002789 return 0;
2790}
2791
Guenter Roeck8969e842012-01-19 11:02:27 -08002792/*
2793 * when Super-I/O functions move to a separate file, the Super-I/O
David Hubbard1ea6dd32007-06-24 11:16:15 +02002794 * bus will manage the lifetime of the device and this module will only keep
2795 * track of the w83627ehf driver. But since we platform_device_alloc(), we
Guenter Roeck8969e842012-01-19 11:02:27 -08002796 * must keep track of the device
2797 */
David Hubbard1ea6dd32007-06-24 11:16:15 +02002798static struct platform_device *pdev;
2799
Jean Delvare08e7e272005-04-25 22:43:25 +02002800static int __init sensors_w83627ehf_init(void)
2801{
David Hubbard1ea6dd32007-06-24 11:16:15 +02002802 int err;
2803 unsigned short address;
2804 struct resource res;
2805 struct w83627ehf_sio_data sio_data;
2806
Guenter Roeck8969e842012-01-19 11:02:27 -08002807 /*
2808 * initialize sio_data->kind and sio_data->sioreg.
David Hubbard1ea6dd32007-06-24 11:16:15 +02002809 *
2810 * when Super-I/O functions move to a separate file, the Super-I/O
2811 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
Guenter Roeck8969e842012-01-19 11:02:27 -08002812 * w83627ehf hardware monitor, and call probe()
2813 */
David Hubbard1ea6dd32007-06-24 11:16:15 +02002814 if (w83627ehf_find(0x2e, &address, &sio_data) &&
2815 w83627ehf_find(0x4e, &address, &sio_data))
Jean Delvare08e7e272005-04-25 22:43:25 +02002816 return -ENODEV;
2817
David Hubbard1ea6dd32007-06-24 11:16:15 +02002818 err = platform_driver_register(&w83627ehf_driver);
2819 if (err)
2820 goto exit;
2821
Guenter Roecke7e1ca62011-02-04 13:24:30 -08002822 pdev = platform_device_alloc(DRVNAME, address);
2823 if (!pdev) {
David Hubbard1ea6dd32007-06-24 11:16:15 +02002824 err = -ENOMEM;
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002825 pr_err("Device allocation failed\n");
David Hubbard1ea6dd32007-06-24 11:16:15 +02002826 goto exit_unregister;
2827 }
2828
2829 err = platform_device_add_data(pdev, &sio_data,
2830 sizeof(struct w83627ehf_sio_data));
2831 if (err) {
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002832 pr_err("Platform data allocation failed\n");
David Hubbard1ea6dd32007-06-24 11:16:15 +02002833 goto exit_device_put;
2834 }
2835
2836 memset(&res, 0, sizeof(res));
2837 res.name = DRVNAME;
2838 res.start = address + IOREGION_OFFSET;
2839 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
2840 res.flags = IORESOURCE_IO;
Jean Delvareb9acb642009-01-07 16:37:35 +01002841
2842 err = acpi_check_resource_conflict(&res);
2843 if (err)
Hans de Goede18632f82009-02-17 19:59:54 +01002844 goto exit_device_put;
Jean Delvareb9acb642009-01-07 16:37:35 +01002845
David Hubbard1ea6dd32007-06-24 11:16:15 +02002846 err = platform_device_add_resources(pdev, &res, 1);
2847 if (err) {
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002848 pr_err("Device resource addition failed (%d)\n", err);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002849 goto exit_device_put;
2850 }
2851
2852 /* platform_device_add calls probe() */
2853 err = platform_device_add(pdev);
2854 if (err) {
Joe Perchesabdc6fd2010-10-20 06:51:54 +00002855 pr_err("Device addition failed (%d)\n", err);
David Hubbard1ea6dd32007-06-24 11:16:15 +02002856 goto exit_device_put;
2857 }
2858
2859 return 0;
2860
2861exit_device_put:
2862 platform_device_put(pdev);
2863exit_unregister:
2864 platform_driver_unregister(&w83627ehf_driver);
2865exit:
2866 return err;
Jean Delvare08e7e272005-04-25 22:43:25 +02002867}
2868
2869static void __exit sensors_w83627ehf_exit(void)
2870{
David Hubbard1ea6dd32007-06-24 11:16:15 +02002871 platform_device_unregister(pdev);
2872 platform_driver_unregister(&w83627ehf_driver);
Jean Delvare08e7e272005-04-25 22:43:25 +02002873}
2874
Jean Delvare7c81c60f2014-01-29 20:40:08 +01002875MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
Jean Delvare08e7e272005-04-25 22:43:25 +02002876MODULE_DESCRIPTION("W83627EHF driver");
2877MODULE_LICENSE("GPL");
2878
2879module_init(sensors_w83627ehf_init);
2880module_exit(sensors_w83627ehf_exit);