blob: bd1c99deac71b73dadf15615c1e8442027bccee9 [file] [log] [blame]
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001/*
2 * nct6775 - Driver for the hardware monitoring functionality of
3 * Nuvoton NCT677x Super-I/O chips
4 *
5 * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
6 *
7 * Derived from w83627ehf driver
Jean Delvare7c81c602014-01-29 20:40:08 +01008 * Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07009 * Copyright (C) 2006 Yuan Mu (Winbond),
10 * Rudolf Marek <r.marek@assembler.cz>
11 * David Hubbard <david.c.hubbard@gmail.com>
12 * Daniel J Blueman <daniel.blueman@gmail.com>
13 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
14 *
15 * Shamelessly ripped from the w83627hf driver
16 * Copyright (C) 2003 Mark Studebaker
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *
33 * Supports the following chips:
34 *
35 * Chip #vin #fan #pwm #temp chip IDs man ID
Guenter Roeck6c009502012-07-01 08:23:15 -070036 * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070037 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
David Bartley578ab5f2013-06-24 22:28:28 -070040 * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
Guenter Roeck8aefb932014-11-16 09:50:04 -080041 * nct6792d 15 6 6 2+6 0xc910 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070042 *
43 * #temp lists the number of monitored temperature sources (first value) plus
44 * the number of directly connectable temperature sensors (second value).
45 */
46
47#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
48
49#include <linux/module.h>
50#include <linux/init.h>
51#include <linux/slab.h>
52#include <linux/jiffies.h>
53#include <linux/platform_device.h>
54#include <linux/hwmon.h>
55#include <linux/hwmon-sysfs.h>
56#include <linux/hwmon-vid.h>
57#include <linux/err.h>
58#include <linux/mutex.h>
59#include <linux/acpi.h>
Guenter Roeck25cdd992015-02-06 18:55:36 -080060#include <linux/dmi.h>
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070061#include <linux/io.h>
62#include "lm75.h"
63
Guenter Roeckaa136e52012-12-04 03:26:05 -080064#define USE_ALTERNATE
65
Guenter Roeck8aefb932014-11-16 09:50:04 -080066enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070067
68/* used to set data->name = nct6775_device_names[data->sio_kind] */
69static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070070 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070071 "nct6775",
72 "nct6776",
73 "nct6779",
David Bartley578ab5f2013-06-24 22:28:28 -070074 "nct6791",
Guenter Roeck8aefb932014-11-16 09:50:04 -080075 "nct6792",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070076};
77
78static unsigned short force_id;
79module_param(force_id, ushort, 0);
80MODULE_PARM_DESC(force_id, "Override the detected device ID");
81
Guenter Roeck47ece962012-12-04 07:59:32 -080082static unsigned short fan_debounce;
83module_param(fan_debounce, ushort, 0);
84MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
85
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070086#define DRVNAME "nct6775"
87
88/*
89 * Super-I/O constants and functions
90 */
91
Guenter Roecka6bd5872012-12-04 03:13:34 -080092#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070093#define NCT6775_LD_HWM 0x0b
94#define NCT6775_LD_VID 0x0d
95
96#define SIO_REG_LDSEL 0x07 /* Logical device select */
97#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
98#define SIO_REG_ENABLE 0x30 /* Logical device enable */
99#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
100
Guenter Roeck6c009502012-07-01 08:23:15 -0700101#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700102#define SIO_NCT6775_ID 0xb470
103#define SIO_NCT6776_ID 0xc330
104#define SIO_NCT6779_ID 0xc560
David Bartley578ab5f2013-06-24 22:28:28 -0700105#define SIO_NCT6791_ID 0xc800
Guenter Roeck8aefb932014-11-16 09:50:04 -0800106#define SIO_NCT6792_ID 0xc910
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700107#define SIO_ID_MASK 0xFFF0
108
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800109enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
110
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700111static inline void
112superio_outb(int ioreg, int reg, int val)
113{
114 outb(reg, ioreg);
115 outb(val, ioreg + 1);
116}
117
118static inline int
119superio_inb(int ioreg, int reg)
120{
121 outb(reg, ioreg);
122 return inb(ioreg + 1);
123}
124
125static inline void
126superio_select(int ioreg, int ld)
127{
128 outb(SIO_REG_LDSEL, ioreg);
129 outb(ld, ioreg + 1);
130}
131
132static inline int
133superio_enter(int ioreg)
134{
135 /*
136 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
137 */
138 if (!request_muxed_region(ioreg, 2, DRVNAME))
139 return -EBUSY;
140
141 outb(0x87, ioreg);
142 outb(0x87, ioreg);
143
144 return 0;
145}
146
147static inline void
148superio_exit(int ioreg)
149{
150 outb(0xaa, ioreg);
151 outb(0x02, ioreg);
152 outb(0x02, ioreg + 1);
153 release_region(ioreg, 2);
154}
155
156/*
157 * ISA constants
158 */
159
160#define IOREGION_ALIGNMENT (~7)
161#define IOREGION_OFFSET 5
162#define IOREGION_LENGTH 2
163#define ADDR_REG_OFFSET 0
164#define DATA_REG_OFFSET 1
165
166#define NCT6775_REG_BANK 0x4E
167#define NCT6775_REG_CONFIG 0x40
168
169/*
170 * Not currently used:
171 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
172 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
173 * REG_MAN_ID is at port 0x4f
174 * REG_CHIP_ID is at port 0x58
175 */
176
Guenter Roeckaa136e52012-12-04 03:26:05 -0800177#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
178#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
179
Guenter Roeck6c009502012-07-01 08:23:15 -0700180#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck30846992013-06-24 22:21:59 -0700181#define NUM_REG_BEEP 5 /* Max number of beep registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700182
David Bartley578ab5f2013-06-24 22:28:28 -0700183#define NUM_FAN 6
184
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700185/* Common and NCT6775 specific data */
186
187/* Voltage min/max registers for nr=7..14 are in bank 5 */
188
189static const u16 NCT6775_REG_IN_MAX[] = {
190 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
191 0x55c, 0x55e, 0x560, 0x562 };
192static const u16 NCT6775_REG_IN_MIN[] = {
193 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
194 0x55d, 0x55f, 0x561, 0x563 };
195static const u16 NCT6775_REG_IN[] = {
196 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
197};
198
199#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800200#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700201#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700202
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800203#define NCT6775_REG_FANDIV1 0x506
204#define NCT6775_REG_FANDIV2 0x507
205
Guenter Roeck47ece962012-12-04 07:59:32 -0800206#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
207
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700208static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
209
Guenter Roeck30846992013-06-24 22:21:59 -0700210/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700211
212static const s8 NCT6775_ALARM_BITS[] = {
213 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
214 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
215 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700216 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700217 -1, -1, -1, /* unused */
218 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
219 12, -1 }; /* intrusion0, intrusion1 */
220
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800221#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800222#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800223#define INTRUSION_ALARM_BASE 30
224
Guenter Roeck30846992013-06-24 22:21:59 -0700225static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
226
227/*
228 * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
229 * 30..31 intrusion
230 */
231static const s8 NCT6775_BEEP_BITS[] = {
232 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
233 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
234 21, /* global beep enable */
235 6, 7, 11, 28, -1, /* fan1..fan5 */
236 -1, -1, -1, /* unused */
237 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
238 12, -1 }; /* intrusion0, intrusion1 */
239
240#define BEEP_ENABLE_BASE 15
241
Guenter Roecka6bd5872012-12-04 03:13:34 -0800242static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
243static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
244
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800245/* DC or PWM output fan configuration */
246static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
247static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
248
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800249/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800250
David Bartley578ab5f2013-06-24 22:28:28 -0700251static const u16 NCT6775_REG_TARGET[] = {
252 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
253static const u16 NCT6775_REG_FAN_MODE[] = {
254 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800255static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700256 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800257static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700258 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800259static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700260 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
261static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
262 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800263static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
264static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
265
266static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700267 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
268static const u16 NCT6775_REG_PWM[] = {
269 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
270static const u16 NCT6775_REG_PWM_READ[] = {
271 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800272
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800273static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
274static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800275static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
David Bartley578ab5f2013-06-24 22:28:28 -0700276static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800277
Guenter Roeckaa136e52012-12-04 03:26:05 -0800278static const u16 NCT6775_REG_TEMP[] = {
279 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
280
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800281static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
282
Guenter Roeckaa136e52012-12-04 03:26:05 -0800283static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
284 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
285static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
286 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
287static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
288 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
289
290static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
291 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
292
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800293static const u16 NCT6775_REG_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700294 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800295
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800296static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700297 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800298static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700299 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800300static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700301 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800302static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700303 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800304static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700305 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800306
Guenter Roeckaa136e52012-12-04 03:26:05 -0800307static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
308
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800309static const u16 NCT6775_REG_AUTO_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700310 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800311static const u16 NCT6775_REG_AUTO_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700312 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800313
314#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
315#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
316
317static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
318
319static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700320 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800321static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700322 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800323
Guenter Roeckaa136e52012-12-04 03:26:05 -0800324static const char *const nct6775_temp_label[] = {
325 "",
326 "SYSTIN",
327 "CPUTIN",
328 "AUXTIN",
329 "AMD SB-TSI",
330 "PECI Agent 0",
331 "PECI Agent 1",
332 "PECI Agent 2",
333 "PECI Agent 3",
334 "PECI Agent 4",
335 "PECI Agent 5",
336 "PECI Agent 6",
337 "PECI Agent 7",
338 "PCH_CHIP_CPU_MAX_TEMP",
339 "PCH_CHIP_TEMP",
340 "PCH_CPU_TEMP",
341 "PCH_MCH_TEMP",
342 "PCH_DIM0_TEMP",
343 "PCH_DIM1_TEMP",
344 "PCH_DIM2_TEMP",
345 "PCH_DIM3_TEMP"
346};
347
348static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
349 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
350
351static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
352 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
353 0xa07 };
354
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700355/* NCT6776 specific data */
356
357static const s8 NCT6776_ALARM_BITS[] = {
358 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
359 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
360 -1, /* unused */
361 6, 7, 11, 10, 23, /* fan1..fan5 */
362 -1, -1, -1, /* unused */
363 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
364 12, 9 }; /* intrusion0, intrusion1 */
365
Guenter Roeck30846992013-06-24 22:21:59 -0700366static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
367
368static const s8 NCT6776_BEEP_BITS[] = {
369 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
370 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
371 24, /* global beep enable */
372 25, 26, 27, 28, 29, /* fan1..fan5 */
373 -1, -1, -1, /* unused */
374 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
375 30, 31 }; /* intrusion0, intrusion1 */
376
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800377static const u16 NCT6776_REG_TOLERANCE_H[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700378 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800379
David Bartley578ab5f2013-06-24 22:28:28 -0700380static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
381static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800382
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800383static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800384static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800385
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800386static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700387 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800388
Guenter Roeckaa136e52012-12-04 03:26:05 -0800389static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
390 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
391
392static const char *const nct6776_temp_label[] = {
393 "",
394 "SYSTIN",
395 "CPUTIN",
396 "AUXTIN",
397 "SMBUSMASTER 0",
398 "SMBUSMASTER 1",
399 "SMBUSMASTER 2",
400 "SMBUSMASTER 3",
401 "SMBUSMASTER 4",
402 "SMBUSMASTER 5",
403 "SMBUSMASTER 6",
404 "SMBUSMASTER 7",
405 "PECI Agent 0",
406 "PECI Agent 1",
407 "PCH_CHIP_CPU_MAX_TEMP",
408 "PCH_CHIP_TEMP",
409 "PCH_CPU_TEMP",
410 "PCH_MCH_TEMP",
411 "PCH_DIM0_TEMP",
412 "PCH_DIM1_TEMP",
413 "PCH_DIM2_TEMP",
414 "PCH_DIM3_TEMP",
415 "BYTE_TEMP"
416};
417
418static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
419 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
420
421static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
422 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
423
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700424/* NCT6779 specific data */
425
426static const u16 NCT6779_REG_IN[] = {
427 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
428 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
429
430static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
431 0x459, 0x45A, 0x45B, 0x568 };
432
433static const s8 NCT6779_ALARM_BITS[] = {
434 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
435 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
436 -1, /* unused */
437 6, 7, 11, 10, 23, /* fan1..fan5 */
438 -1, -1, -1, /* unused */
439 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
440 12, 9 }; /* intrusion0, intrusion1 */
441
Guenter Roeck30846992013-06-24 22:21:59 -0700442static const s8 NCT6779_BEEP_BITS[] = {
443 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
444 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
445 24, /* global beep enable */
446 25, 26, 27, 28, 29, /* fan1..fan5 */
447 -1, -1, -1, /* unused */
448 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
449 30, 31 }; /* intrusion0, intrusion1 */
450
David Bartley578ab5f2013-06-24 22:28:28 -0700451static const u16 NCT6779_REG_FAN[] = {
452 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800453static const u16 NCT6779_REG_FAN_PULSES[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700454 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800455
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800456static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700457 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700458#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800459static const u16 NCT6779_REG_CRITICAL_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700460 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800461
Guenter Roeckaa136e52012-12-04 03:26:05 -0800462static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800463static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
Guenter Roeckaa136e52012-12-04 03:26:05 -0800464static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
465 0x18, 0x152 };
466static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
467 0x3a, 0x153 };
468static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
469 0x39, 0x155 };
470
471static const u16 NCT6779_REG_TEMP_OFFSET[] = {
472 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
473
474static const char *const nct6779_temp_label[] = {
475 "",
476 "SYSTIN",
477 "CPUTIN",
478 "AUXTIN0",
479 "AUXTIN1",
480 "AUXTIN2",
481 "AUXTIN3",
482 "",
483 "SMBUSMASTER 0",
484 "SMBUSMASTER 1",
485 "SMBUSMASTER 2",
486 "SMBUSMASTER 3",
487 "SMBUSMASTER 4",
488 "SMBUSMASTER 5",
489 "SMBUSMASTER 6",
490 "SMBUSMASTER 7",
491 "PECI Agent 0",
492 "PECI Agent 1",
493 "PCH_CHIP_CPU_MAX_TEMP",
494 "PCH_CHIP_TEMP",
495 "PCH_CPU_TEMP",
496 "PCH_MCH_TEMP",
497 "PCH_DIM0_TEMP",
498 "PCH_DIM1_TEMP",
499 "PCH_DIM2_TEMP",
500 "PCH_DIM3_TEMP",
501 "BYTE_TEMP"
502};
503
504static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
505 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
506 0, 0, 0, 0, 0, 0, 0, 0,
507 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
508 0x408, 0 };
509
510static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
511 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
512
David Bartley578ab5f2013-06-24 22:28:28 -0700513/* NCT6791 specific data */
514
515#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
516
Guenter Roeckcc76dee2013-11-13 12:47:17 -0800517static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[6] = { 0, 0x239 };
518static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[6] = { 0, 0x23a };
519static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[6] = { 0, 0x23b };
520static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[6] = { 0, 0x23c };
521static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[6] = { 0, 0x23d };
522static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[6] = { 0, 0x23e };
523
David Bartley578ab5f2013-06-24 22:28:28 -0700524static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
525 0x459, 0x45A, 0x45B, 0x568, 0x45D };
526
527static const s8 NCT6791_ALARM_BITS[] = {
528 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
529 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
530 -1, /* unused */
531 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
532 -1, -1, /* unused */
533 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
534 12, 9 }; /* intrusion0, intrusion1 */
535
Guenter Roeck8aefb932014-11-16 09:50:04 -0800536/* NCT6792 specific data */
537
538static const u16 NCT6792_REG_TEMP_MON[] = {
539 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
540static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
541 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
David Bartley578ab5f2013-06-24 22:28:28 -0700542
Guenter Roeck6c009502012-07-01 08:23:15 -0700543/* NCT6102D/NCT6106D specific data */
544
545#define NCT6106_REG_VBAT 0x318
546#define NCT6106_REG_DIODE 0x319
547#define NCT6106_DIODE_MASK 0x01
548
549static const u16 NCT6106_REG_IN_MAX[] = {
550 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
551static const u16 NCT6106_REG_IN_MIN[] = {
552 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
553static const u16 NCT6106_REG_IN[] = {
554 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
555
556static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800557static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
Guenter Roeck6c009502012-07-01 08:23:15 -0700558static const u16 NCT6106_REG_TEMP_HYST[] = {
559 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
560static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700561 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
562static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
563 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
564static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
565 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700566static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
567static const u16 NCT6106_REG_TEMP_CONFIG[] = {
568 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
569
570static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
571static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
572static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
573static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
574
575static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
576static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
577static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
578static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
579static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
580static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
581static const u16 NCT6106_REG_TEMP_SOURCE[] = {
582 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
583
584static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
585static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
586 0x11b, 0x12b, 0x13b };
587
588static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
589#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
590static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
591
592static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
593static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
594static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
595static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
596static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
597static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
598
599static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
600
601static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
602static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
603static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
604static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
605static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
606static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
607
608static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
609static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
610
611static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
612 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
613
614static const s8 NCT6106_ALARM_BITS[] = {
615 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
616 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
617 -1, /* unused */
618 32, 33, 34, -1, -1, /* fan1..fan5 */
619 -1, -1, -1, /* unused */
620 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
621 48, -1 /* intrusion0, intrusion1 */
622};
623
Guenter Roeck30846992013-06-24 22:21:59 -0700624static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
625 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
626
627static const s8 NCT6106_BEEP_BITS[] = {
628 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
629 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
630 32, /* global beep enable */
631 24, 25, 26, 27, 28, /* fan1..fan5 */
632 -1, -1, -1, /* unused */
633 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
634 34, -1 /* intrusion0, intrusion1 */
635};
636
Guenter Roeck6c009502012-07-01 08:23:15 -0700637static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
638 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
639
640static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
641 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
642
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800643static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
644{
645 if (mode == 0 && pwm == 255)
646 return off;
647 return mode + 1;
648}
649
650static int pwm_enable_to_reg(enum pwm_enable mode)
651{
652 if (mode == off)
653 return 0;
654 return mode - 1;
655}
656
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700657/*
658 * Conversions
659 */
660
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800661/* 1 is DC mode, output in ms */
662static unsigned int step_time_from_reg(u8 reg, u8 mode)
663{
664 return mode ? 400 * reg : 100 * reg;
665}
666
667static u8 step_time_to_reg(unsigned int msec, u8 mode)
668{
669 return clamp_val((mode ? (msec + 200) / 400 :
670 (msec + 50) / 100), 1, 255);
671}
672
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800673static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
674{
675 if (reg == 0 || reg == 255)
676 return 0;
677 return 1350000U / (reg << divreg);
678}
679
680static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
681{
682 if ((reg & 0xff1f) == 0xff1f)
683 return 0;
684
685 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
686
687 if (reg == 0)
688 return 0;
689
690 return 1350000U / reg;
691}
692
693static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
694{
695 if (reg == 0 || reg == 0xffff)
696 return 0;
697
698 /*
699 * Even though the registers are 16 bit wide, the fan divisor
700 * still applies.
701 */
702 return 1350000U / (reg << divreg);
703}
704
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800705static u16 fan_to_reg(u32 fan, unsigned int divreg)
706{
707 if (!fan)
708 return 0;
709
710 return (1350000U / fan) >> divreg;
711}
712
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800713static inline unsigned int
714div_from_reg(u8 reg)
715{
716 return 1 << reg;
717}
718
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700719/*
720 * Some of the voltage inputs have internal scaling, the tables below
721 * contain 8 (the ADC LSB in mV) * scaling factor * 100
722 */
723static const u16 scale_in[15] = {
724 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
725 800, 800
726};
727
728static inline long in_from_reg(u8 reg, u8 nr)
729{
730 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
731}
732
733static inline u8 in_to_reg(u32 val, u8 nr)
734{
735 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
736}
737
738/*
739 * Data structures and manipulation thereof
740 */
741
742struct nct6775_data {
743 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700744 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700745 enum kinds kind;
746 const char *name;
747
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700748 const struct attribute_group *groups[6];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700749
Guenter Roeckb7a61352013-04-02 22:14:06 -0700750 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
751 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800752 */
753 u8 temp_src[NUM_TEMP];
754 u16 reg_temp_config[NUM_TEMP];
755 const char * const *temp_label;
756 int temp_label_num;
757
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700758 u16 REG_CONFIG;
759 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800760 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700761 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700762
763 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700764 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700765
766 const u16 *REG_VIN;
767 const u16 *REG_IN_MINMAX[2];
768
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800769 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800770 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800771 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800772 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800773 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700774 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800775 const u16 *REG_FAN_TIME[3];
776
777 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800778
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800779 const u8 *REG_PWM_MODE;
780 const u8 *PWM_MODE_MASK;
781
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800782 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
783 * [3]=pwm_max, [4]=pwm_step,
784 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800785 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800786 const u16 *REG_PWM_READ;
787
Guenter Roeck6c009502012-07-01 08:23:15 -0700788 const u16 *REG_CRITICAL_PWM_ENABLE;
789 u8 CRITICAL_PWM_ENABLE_MASK;
790 const u16 *REG_CRITICAL_PWM;
791
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800792 const u16 *REG_AUTO_TEMP;
793 const u16 *REG_AUTO_PWM;
794
795 const u16 *REG_CRITICAL_TEMP;
796 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
797
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800798 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800799 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800800 const u16 *REG_WEIGHT_TEMP_SEL;
801 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
802
Guenter Roeckaa136e52012-12-04 03:26:05 -0800803 const u16 *REG_TEMP_OFFSET;
804
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700805 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700806 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700807
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800808 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
809 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
810
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700811 struct mutex update_lock;
812 bool valid; /* true if following fields are valid */
813 unsigned long last_updated; /* In jiffies */
814
815 /* Register values */
816 u8 bank; /* current register bank */
817 u8 in_num; /* number of in inputs we have */
818 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700819 unsigned int rpm[NUM_FAN];
820 u16 fan_min[NUM_FAN];
821 u8 fan_pulses[NUM_FAN];
822 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800823 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800824 u8 has_fan; /* some fan inputs can be disabled */
825 u8 has_fan_min; /* some fans don't have min register */
826 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700827
Guenter Roeck6c009502012-07-01 08:23:15 -0700828 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700829 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800830 u8 temp_fixed_num; /* 3 or 6 */
831 u8 temp_type[NUM_TEMP_FIXED];
832 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300833 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
834 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700835 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700836 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700837
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800838 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700839 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
840 * 0->PWM variable duty cycle
841 */
842 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800843 /* 0->off
844 * 1->manual
845 * 2->thermal cruise mode (also called SmartFan I)
846 * 3->fan speed cruise mode
847 * 4->SmartFan III
848 * 5->enhanced variable thermal cruise (SmartFan IV)
849 */
David Bartley578ab5f2013-06-24 22:28:28 -0700850 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
851 * [3]=pwm_max, [4]=pwm_step,
852 * [5]=weight_duty_step, [6]=weight_duty_base
853 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800854
David Bartley578ab5f2013-06-24 22:28:28 -0700855 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800856 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700857 u32 target_speed[NUM_FAN];
858 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800859 u8 speed_tolerance_limit;
860
David Bartley578ab5f2013-06-24 22:28:28 -0700861 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800862 u8 tolerance_mask;
863
David Bartley578ab5f2013-06-24 22:28:28 -0700864 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800865
866 /* Automatic fan speed control registers */
867 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700868 u8 auto_pwm[NUM_FAN][7];
869 u8 auto_temp[NUM_FAN][7];
870 u8 pwm_temp_sel[NUM_FAN];
871 u8 pwm_weight_temp_sel[NUM_FAN];
872 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
873 * 2->temp_base
874 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800875
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700876 u8 vid;
877 u8 vrm;
878
Guenter Roeckf73cf632013-03-18 09:22:50 -0700879 bool have_vid;
880
Guenter Roeckaa136e52012-12-04 03:26:05 -0800881 u16 have_temp;
882 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700883 u16 have_in;
Guenter Roeck48e93182015-02-07 08:48:49 -0800884
Guenter Roeck84d19d92012-12-04 08:01:39 -0800885 /* Remember extra register values over suspend/resume */
886 u8 vbat;
887 u8 fandiv1;
888 u8 fandiv2;
Guenter Roeckd2a14ea2015-02-06 18:53:21 -0800889 u8 sio_reg_enable;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700890};
891
892struct nct6775_sio_data {
893 int sioreg;
894 enum kinds kind;
895};
896
Guenter Roeckf73cf632013-03-18 09:22:50 -0700897struct sensor_device_template {
898 struct device_attribute dev_attr;
899 union {
900 struct {
901 u8 nr;
902 u8 index;
903 } s;
904 int index;
905 } u;
906 bool s2; /* true if both index and nr are used */
907};
908
909struct sensor_device_attr_u {
910 union {
911 struct sensor_device_attribute a1;
912 struct sensor_device_attribute_2 a2;
913 } u;
914 char name[32];
915};
916
917#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
918 .attr = {.name = _template, .mode = _mode }, \
919 .show = _show, \
920 .store = _store, \
921}
922
923#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
924 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
925 .u.index = _index, \
926 .s2 = false }
927
928#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
929 _nr, _index) \
930 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
931 .u.s.index = _index, \
932 .u.s.nr = _nr, \
933 .s2 = true }
934
935#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
936static struct sensor_device_template sensor_dev_template_##_name \
937 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
938 _index)
939
940#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
941 _nr, _index) \
942static struct sensor_device_template sensor_dev_template_##_name \
943 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
944 _nr, _index)
945
946struct sensor_template_group {
947 struct sensor_device_template **templates;
948 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
949 int base;
950};
951
952static struct attribute_group *
953nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
954 int repeat)
955{
956 struct attribute_group *group;
957 struct sensor_device_attr_u *su;
958 struct sensor_device_attribute *a;
959 struct sensor_device_attribute_2 *a2;
960 struct attribute **attrs;
961 struct sensor_device_template **t;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300962 int i, count;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700963
964 if (repeat <= 0)
965 return ERR_PTR(-EINVAL);
966
967 t = tg->templates;
968 for (count = 0; *t; t++, count++)
969 ;
970
971 if (count == 0)
972 return ERR_PTR(-EINVAL);
973
974 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
975 if (group == NULL)
976 return ERR_PTR(-ENOMEM);
977
978 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
979 GFP_KERNEL);
980 if (attrs == NULL)
981 return ERR_PTR(-ENOMEM);
982
983 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
984 GFP_KERNEL);
985 if (su == NULL)
986 return ERR_PTR(-ENOMEM);
987
988 group->attrs = attrs;
989 group->is_visible = tg->is_visible;
990
991 for (i = 0; i < repeat; i++) {
992 t = tg->templates;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300993 while (*t != NULL) {
Guenter Roeckf73cf632013-03-18 09:22:50 -0700994 snprintf(su->name, sizeof(su->name),
995 (*t)->dev_attr.attr.name, tg->base + i);
996 if ((*t)->s2) {
997 a2 = &su->u.a2;
Guenter Roeck1b63bf62015-05-28 09:08:09 -0700998 sysfs_attr_init(&a2->dev_attr.attr);
Guenter Roeckf73cf632013-03-18 09:22:50 -0700999 a2->dev_attr.attr.name = su->name;
1000 a2->nr = (*t)->u.s.nr + i;
1001 a2->index = (*t)->u.s.index;
1002 a2->dev_attr.attr.mode =
1003 (*t)->dev_attr.attr.mode;
1004 a2->dev_attr.show = (*t)->dev_attr.show;
1005 a2->dev_attr.store = (*t)->dev_attr.store;
1006 *attrs = &a2->dev_attr.attr;
1007 } else {
1008 a = &su->u.a1;
Guenter Roeck1b63bf62015-05-28 09:08:09 -07001009 sysfs_attr_init(&a->dev_attr.attr);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001010 a->dev_attr.attr.name = su->name;
1011 a->index = (*t)->u.index + i;
1012 a->dev_attr.attr.mode =
1013 (*t)->dev_attr.attr.mode;
1014 a->dev_attr.show = (*t)->dev_attr.show;
1015 a->dev_attr.store = (*t)->dev_attr.store;
1016 *attrs = &a->dev_attr.attr;
1017 }
1018 attrs++;
1019 su++;
1020 t++;
1021 }
1022 }
1023
Guenter Roeckf73cf632013-03-18 09:22:50 -07001024 return group;
1025}
1026
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001027static bool is_word_sized(struct nct6775_data *data, u16 reg)
1028{
1029 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001030 case nct6106:
1031 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1032 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1033 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001034 case nct6775:
1035 return (((reg & 0xff00) == 0x100 ||
1036 (reg & 0xff00) == 0x200) &&
1037 ((reg & 0x00ff) == 0x50 ||
1038 (reg & 0x00ff) == 0x53 ||
1039 (reg & 0x00ff) == 0x55)) ||
1040 (reg & 0xfff0) == 0x630 ||
1041 reg == 0x640 || reg == 0x642 ||
1042 reg == 0x662 ||
1043 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1044 reg == 0x73 || reg == 0x75 || reg == 0x77;
1045 case nct6776:
1046 return (((reg & 0xff00) == 0x100 ||
1047 (reg & 0xff00) == 0x200) &&
1048 ((reg & 0x00ff) == 0x50 ||
1049 (reg & 0x00ff) == 0x53 ||
1050 (reg & 0x00ff) == 0x55)) ||
1051 (reg & 0xfff0) == 0x630 ||
1052 reg == 0x402 ||
1053 reg == 0x640 || reg == 0x642 ||
1054 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1055 reg == 0x73 || reg == 0x75 || reg == 0x77;
1056 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001057 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08001058 case nct6792:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001059 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001060 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001061 reg == 0x402 ||
1062 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1063 reg == 0x640 || reg == 0x642 ||
1064 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
Guenter Roeck8aefb932014-11-16 09:50:04 -08001065 reg == 0x7b || reg == 0x7d;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001066 }
1067 return false;
1068}
1069
1070/*
1071 * On older chips, only registers 0x50-0x5f are banked.
1072 * On more recent chips, all registers are banked.
1073 * Assume that is the case and set the bank number for each access.
1074 * Cache the bank number so it only needs to be set if it changes.
1075 */
1076static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1077{
1078 u8 bank = reg >> 8;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001079
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001080 if (data->bank != bank) {
1081 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1082 outb_p(bank, data->addr + DATA_REG_OFFSET);
1083 data->bank = bank;
1084 }
1085}
1086
1087static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1088{
1089 int res, word_sized = is_word_sized(data, reg);
1090
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001091 nct6775_set_bank(data, reg);
1092 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1093 res = inb_p(data->addr + DATA_REG_OFFSET);
1094 if (word_sized) {
1095 outb_p((reg & 0xff) + 1,
1096 data->addr + ADDR_REG_OFFSET);
1097 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1098 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001099 return res;
1100}
1101
1102static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1103{
1104 int word_sized = is_word_sized(data, reg);
1105
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001106 nct6775_set_bank(data, reg);
1107 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1108 if (word_sized) {
1109 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1110 outb_p((reg & 0xff) + 1,
1111 data->addr + ADDR_REG_OFFSET);
1112 }
1113 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001114 return 0;
1115}
1116
Guenter Roeckaa136e52012-12-04 03:26:05 -08001117/* We left-align 8-bit temperature values to make the code simpler */
1118static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1119{
1120 u16 res;
1121
1122 res = nct6775_read_value(data, reg);
1123 if (!is_word_sized(data, reg))
1124 res <<= 8;
1125
1126 return res;
1127}
1128
1129static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1130{
1131 if (!is_word_sized(data, reg))
1132 value >>= 8;
1133 return nct6775_write_value(data, reg, value);
1134}
1135
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001136/* This function assumes that the caller holds data->update_lock */
1137static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1138{
1139 u8 reg;
1140
1141 switch (nr) {
1142 case 0:
1143 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1144 | (data->fan_div[0] & 0x7);
1145 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1146 break;
1147 case 1:
1148 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1149 | ((data->fan_div[1] << 4) & 0x70);
1150 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1151 break;
1152 case 2:
1153 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1154 | (data->fan_div[2] & 0x7);
1155 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1156 break;
1157 case 3:
1158 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1159 | ((data->fan_div[3] << 4) & 0x70);
1160 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1161 break;
1162 }
1163}
1164
1165static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1166{
1167 if (data->kind == nct6775)
1168 nct6775_write_fan_div(data, nr);
1169}
1170
1171static void nct6775_update_fan_div(struct nct6775_data *data)
1172{
1173 u8 i;
1174
1175 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1176 data->fan_div[0] = i & 0x7;
1177 data->fan_div[1] = (i & 0x70) >> 4;
1178 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1179 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001180 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001181 data->fan_div[3] = (i & 0x70) >> 4;
1182}
1183
1184static void nct6775_update_fan_div_common(struct nct6775_data *data)
1185{
1186 if (data->kind == nct6775)
1187 nct6775_update_fan_div(data);
1188}
1189
1190static void nct6775_init_fan_div(struct nct6775_data *data)
1191{
1192 int i;
1193
1194 nct6775_update_fan_div_common(data);
1195 /*
1196 * For all fans, start with highest divider value if the divider
1197 * register is not initialized. This ensures that we get a
1198 * reading from the fan count register, even if it is not optimal.
1199 * We'll compute a better divider later on.
1200 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001201 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001202 if (!(data->has_fan & (1 << i)))
1203 continue;
1204 if (data->fan_div[i] == 0) {
1205 data->fan_div[i] = 7;
1206 nct6775_write_fan_div_common(data, i);
1207 }
1208 }
1209}
1210
1211static void nct6775_init_fan_common(struct device *dev,
1212 struct nct6775_data *data)
1213{
1214 int i;
1215 u8 reg;
1216
1217 if (data->has_fan_div)
1218 nct6775_init_fan_div(data);
1219
1220 /*
1221 * If fan_min is not set (0), set it to 0xff to disable it. This
1222 * prevents the unnecessary warning when fanX_min is reported as 0.
1223 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001224 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001225 if (data->has_fan_min & (1 << i)) {
1226 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1227 if (!reg)
1228 nct6775_write_value(data, data->REG_FAN_MIN[i],
1229 data->has_fan_div ? 0xff
1230 : 0xff1f);
1231 }
1232 }
1233}
1234
1235static void nct6775_select_fan_div(struct device *dev,
1236 struct nct6775_data *data, int nr, u16 reg)
1237{
1238 u8 fan_div = data->fan_div[nr];
1239 u16 fan_min;
1240
1241 if (!data->has_fan_div)
1242 return;
1243
1244 /*
1245 * If we failed to measure the fan speed, or the reported value is not
1246 * in the optimal range, and the clock divider can be modified,
1247 * let's try that for next time.
1248 */
1249 if (reg == 0x00 && fan_div < 0x07)
1250 fan_div++;
1251 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1252 fan_div--;
1253
1254 if (fan_div != data->fan_div[nr]) {
1255 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1256 nr + 1, div_from_reg(data->fan_div[nr]),
1257 div_from_reg(fan_div));
1258
1259 /* Preserve min limit if possible */
1260 if (data->has_fan_min & (1 << nr)) {
1261 fan_min = data->fan_min[nr];
1262 if (fan_div > data->fan_div[nr]) {
1263 if (fan_min != 255 && fan_min > 1)
1264 fan_min >>= 1;
1265 } else {
1266 if (fan_min != 255) {
1267 fan_min <<= 1;
1268 if (fan_min > 254)
1269 fan_min = 254;
1270 }
1271 }
1272 if (fan_min != data->fan_min[nr]) {
1273 data->fan_min[nr] = fan_min;
1274 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1275 fan_min);
1276 }
1277 }
1278 data->fan_div[nr] = fan_div;
1279 nct6775_write_fan_div_common(data, nr);
1280 }
1281}
1282
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001283static void nct6775_update_pwm(struct device *dev)
1284{
1285 struct nct6775_data *data = dev_get_drvdata(dev);
1286 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001287 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001288 bool duty_is_dc;
1289
1290 for (i = 0; i < data->pwm_num; i++) {
1291 if (!(data->has_pwm & (1 << i)))
1292 continue;
1293
1294 duty_is_dc = data->REG_PWM_MODE[i] &&
1295 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1296 & data->PWM_MODE_MASK[i]);
1297 data->pwm_mode[i] = duty_is_dc;
1298
1299 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1300 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1301 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1302 data->pwm[j][i]
1303 = nct6775_read_value(data,
1304 data->REG_PWM[j][i]);
1305 }
1306 }
1307
1308 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1309 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001310
1311 if (!data->temp_tolerance[0][i] ||
1312 data->pwm_enable[i] != speed_cruise)
1313 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1314 if (!data->target_speed_tolerance[i] ||
1315 data->pwm_enable[i] == speed_cruise) {
1316 u8 t = fanmodecfg & 0x0f;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001317
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001318 if (data->REG_TOLERANCE_H) {
1319 t |= (nct6775_read_value(data,
1320 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1321 }
1322 data->target_speed_tolerance[i] = t;
1323 }
1324
1325 data->temp_tolerance[1][i] =
1326 nct6775_read_value(data,
1327 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1328
1329 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1330 data->pwm_temp_sel[i] = reg & 0x1f;
1331 /* If fan can stop, report floor as 0 */
1332 if (reg & 0x80)
1333 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001334
Guenter Roeckcc76dee2013-11-13 12:47:17 -08001335 if (!data->REG_WEIGHT_TEMP_SEL[i])
1336 continue;
1337
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001338 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1339 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1340 /* If weight is disabled, report weight source as 0 */
1341 if (j == 1 && !(reg & 0x80))
1342 data->pwm_weight_temp_sel[i] = 0;
1343
1344 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001345 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001346 data->weight_temp[j][i]
1347 = nct6775_read_value(data,
1348 data->REG_WEIGHT_TEMP[j][i]);
1349 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001350 }
1351}
1352
1353static void nct6775_update_pwm_limits(struct device *dev)
1354{
1355 struct nct6775_data *data = dev_get_drvdata(dev);
1356 int i, j;
1357 u8 reg;
1358 u16 reg_t;
1359
1360 for (i = 0; i < data->pwm_num; i++) {
1361 if (!(data->has_pwm & (1 << i)))
1362 continue;
1363
Guenter Roeckc409fd42013-04-09 05:04:00 -07001364 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001365 data->fan_time[j][i] =
1366 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1367 }
1368
1369 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1370 /* Update only in matching mode or if never updated */
1371 if (!data->target_temp[i] ||
1372 data->pwm_enable[i] == thermal_cruise)
1373 data->target_temp[i] = reg_t & data->target_temp_mask;
1374 if (!data->target_speed[i] ||
1375 data->pwm_enable[i] == speed_cruise) {
1376 if (data->REG_TOLERANCE_H) {
1377 reg_t |= (nct6775_read_value(data,
1378 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1379 }
1380 data->target_speed[i] = reg_t;
1381 }
1382
1383 for (j = 0; j < data->auto_pwm_num; j++) {
1384 data->auto_pwm[i][j] =
1385 nct6775_read_value(data,
1386 NCT6775_AUTO_PWM(data, i, j));
1387 data->auto_temp[i][j] =
1388 nct6775_read_value(data,
1389 NCT6775_AUTO_TEMP(data, i, j));
1390 }
1391
1392 /* critical auto_pwm temperature data */
1393 data->auto_temp[i][data->auto_pwm_num] =
1394 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1395
1396 switch (data->kind) {
1397 case nct6775:
1398 reg = nct6775_read_value(data,
1399 NCT6775_REG_CRITICAL_ENAB[i]);
1400 data->auto_pwm[i][data->auto_pwm_num] =
1401 (reg & 0x02) ? 0xff : 0x00;
1402 break;
1403 case nct6776:
1404 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1405 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001406 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001407 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001408 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08001409 case nct6792:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001410 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001411 data->REG_CRITICAL_PWM_ENABLE[i]);
1412 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1413 reg = nct6775_read_value(data,
1414 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001415 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001416 reg = 0xff;
1417 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001418 break;
1419 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001420 }
1421}
1422
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001423static struct nct6775_data *nct6775_update_device(struct device *dev)
1424{
1425 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001426 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001427
1428 mutex_lock(&data->update_lock);
1429
Guenter Roeck6445e662013-04-21 09:13:28 -07001430 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001431 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001432 /* Fan clock dividers */
1433 nct6775_update_fan_div_common(data);
1434
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001435 /* Measured voltages and limits */
1436 for (i = 0; i < data->in_num; i++) {
1437 if (!(data->have_in & (1 << i)))
1438 continue;
1439
1440 data->in[i][0] = nct6775_read_value(data,
1441 data->REG_VIN[i]);
1442 data->in[i][1] = nct6775_read_value(data,
1443 data->REG_IN_MINMAX[0][i]);
1444 data->in[i][2] = nct6775_read_value(data,
1445 data->REG_IN_MINMAX[1][i]);
1446 }
1447
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001448 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001449 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001450 u16 reg;
1451
1452 if (!(data->has_fan & (1 << i)))
1453 continue;
1454
1455 reg = nct6775_read_value(data, data->REG_FAN[i]);
1456 data->rpm[i] = data->fan_from_reg(reg,
1457 data->fan_div[i]);
1458
1459 if (data->has_fan_min & (1 << i))
1460 data->fan_min[i] = nct6775_read_value(data,
1461 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001462 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001463 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1464 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001465
1466 nct6775_select_fan_div(dev, data, i, reg);
1467 }
1468
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001469 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001470 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001471
Guenter Roeckaa136e52012-12-04 03:26:05 -08001472 /* Measured temperatures and limits */
1473 for (i = 0; i < NUM_TEMP; i++) {
1474 if (!(data->have_temp & (1 << i)))
1475 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001476 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001477 if (data->reg_temp[j][i])
1478 data->temp[j][i]
1479 = nct6775_read_temp(data,
1480 data->reg_temp[j][i]);
1481 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001482 if (i >= NUM_TEMP_FIXED ||
1483 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001484 continue;
1485 data->temp_offset[i]
1486 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1487 }
1488
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001489 data->alarms = 0;
1490 for (i = 0; i < NUM_REG_ALARM; i++) {
1491 u8 alarm;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001492
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001493 if (!data->REG_ALARM[i])
1494 continue;
1495 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1496 data->alarms |= ((u64)alarm) << (i << 3);
1497 }
1498
Guenter Roeck30846992013-06-24 22:21:59 -07001499 data->beeps = 0;
1500 for (i = 0; i < NUM_REG_BEEP; i++) {
1501 u8 beep;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001502
Guenter Roeck30846992013-06-24 22:21:59 -07001503 if (!data->REG_BEEP[i])
1504 continue;
1505 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1506 data->beeps |= ((u64)beep) << (i << 3);
1507 }
1508
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001509 data->last_updated = jiffies;
1510 data->valid = true;
1511 }
1512
1513 mutex_unlock(&data->update_lock);
1514 return data;
1515}
1516
1517/*
1518 * Sysfs callback functions
1519 */
1520static ssize_t
1521show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1522{
1523 struct nct6775_data *data = nct6775_update_device(dev);
1524 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001525 int index = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001526 int nr = sattr->nr;
1527
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001528 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1529}
1530
1531static ssize_t
1532store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1533 size_t count)
1534{
1535 struct nct6775_data *data = dev_get_drvdata(dev);
1536 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001537 int index = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001538 int nr = sattr->nr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001539 unsigned long val;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001540 int err;
1541
1542 err = kstrtoul(buf, 10, &val);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001543 if (err < 0)
1544 return err;
1545 mutex_lock(&data->update_lock);
1546 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001547 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001548 data->in[nr][index]);
1549 mutex_unlock(&data->update_lock);
1550 return count;
1551}
1552
1553static ssize_t
1554show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1555{
1556 struct nct6775_data *data = nct6775_update_device(dev);
1557 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1558 int nr = data->ALARM_BITS[sattr->index];
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001559
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001560 return sprintf(buf, "%u\n",
1561 (unsigned int)((data->alarms >> nr) & 0x01));
1562}
1563
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001564static int find_temp_source(struct nct6775_data *data, int index, int count)
1565{
1566 int source = data->temp_src[index];
1567 int nr;
1568
1569 for (nr = 0; nr < count; nr++) {
1570 int src;
1571
1572 src = nct6775_read_value(data,
1573 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1574 if (src == source)
1575 return nr;
1576 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001577 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001578}
1579
1580static ssize_t
1581show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1582{
1583 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1584 struct nct6775_data *data = nct6775_update_device(dev);
1585 unsigned int alarm = 0;
1586 int nr;
1587
1588 /*
1589 * For temperatures, there is no fixed mapping from registers to alarm
1590 * bits. Alarm bits are determined by the temperature source mapping.
1591 */
1592 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1593 if (nr >= 0) {
1594 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001595
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001596 alarm = (data->alarms >> bit) & 0x01;
1597 }
1598 return sprintf(buf, "%u\n", alarm);
1599}
1600
Guenter Roeck30846992013-06-24 22:21:59 -07001601static ssize_t
1602show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1603{
1604 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1605 struct nct6775_data *data = nct6775_update_device(dev);
1606 int nr = data->BEEP_BITS[sattr->index];
1607
1608 return sprintf(buf, "%u\n",
1609 (unsigned int)((data->beeps >> nr) & 0x01));
1610}
1611
1612static ssize_t
1613store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1614 size_t count)
1615{
1616 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1617 struct nct6775_data *data = dev_get_drvdata(dev);
1618 int nr = data->BEEP_BITS[sattr->index];
1619 int regindex = nr >> 3;
1620 unsigned long val;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001621 int err;
Guenter Roeck30846992013-06-24 22:21:59 -07001622
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001623 err = kstrtoul(buf, 10, &val);
Guenter Roeck30846992013-06-24 22:21:59 -07001624 if (err < 0)
1625 return err;
1626 if (val > 1)
1627 return -EINVAL;
1628
1629 mutex_lock(&data->update_lock);
1630 if (val)
1631 data->beeps |= (1ULL << nr);
1632 else
1633 data->beeps &= ~(1ULL << nr);
1634 nct6775_write_value(data, data->REG_BEEP[regindex],
1635 (data->beeps >> (regindex << 3)) & 0xff);
1636 mutex_unlock(&data->update_lock);
1637 return count;
1638}
1639
1640static ssize_t
1641show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1642{
1643 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1644 struct nct6775_data *data = nct6775_update_device(dev);
1645 unsigned int beep = 0;
1646 int nr;
1647
1648 /*
1649 * For temperatures, there is no fixed mapping from registers to beep
1650 * enable bits. Beep enable bits are determined by the temperature
1651 * source mapping.
1652 */
1653 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1654 if (nr >= 0) {
1655 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001656
Guenter Roeck30846992013-06-24 22:21:59 -07001657 beep = (data->beeps >> bit) & 0x01;
1658 }
1659 return sprintf(buf, "%u\n", beep);
1660}
1661
1662static ssize_t
1663store_temp_beep(struct device *dev, struct device_attribute *attr,
1664 const char *buf, size_t count)
1665{
1666 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1667 struct nct6775_data *data = dev_get_drvdata(dev);
1668 int nr, bit, regindex;
1669 unsigned long val;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001670 int err;
Guenter Roeck30846992013-06-24 22:21:59 -07001671
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001672 err = kstrtoul(buf, 10, &val);
Guenter Roeck30846992013-06-24 22:21:59 -07001673 if (err < 0)
1674 return err;
1675 if (val > 1)
1676 return -EINVAL;
1677
1678 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1679 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001680 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001681
1682 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1683 regindex = bit >> 3;
1684
1685 mutex_lock(&data->update_lock);
1686 if (val)
1687 data->beeps |= (1ULL << bit);
1688 else
1689 data->beeps &= ~(1ULL << bit);
1690 nct6775_write_value(data, data->REG_BEEP[regindex],
1691 (data->beeps >> (regindex << 3)) & 0xff);
1692 mutex_unlock(&data->update_lock);
1693
1694 return count;
1695}
1696
Guenter Roeckf73cf632013-03-18 09:22:50 -07001697static umode_t nct6775_in_is_visible(struct kobject *kobj,
1698 struct attribute *attr, int index)
1699{
1700 struct device *dev = container_of(kobj, struct device, kobj);
1701 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001702 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001703
Guenter Roeckf73cf632013-03-18 09:22:50 -07001704 if (!(data->have_in & (1 << in)))
1705 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001706
Guenter Roeckf73cf632013-03-18 09:22:50 -07001707 return attr->mode;
1708}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001709
Guenter Roeckf73cf632013-03-18 09:22:50 -07001710SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1711SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001712SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1713 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001714SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1715 store_in_reg, 0, 1);
1716SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1717 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001718
Guenter Roeckf73cf632013-03-18 09:22:50 -07001719/*
1720 * nct6775_in_is_visible uses the index into the following array
1721 * to determine if attributes should be created or not.
1722 * Any change in order or content must be matched.
1723 */
1724static struct sensor_device_template *nct6775_attributes_in_template[] = {
1725 &sensor_dev_template_in_input,
1726 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001727 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001728 &sensor_dev_template_in_min,
1729 &sensor_dev_template_in_max,
1730 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001731};
1732
Guenter Roeckf73cf632013-03-18 09:22:50 -07001733static struct sensor_template_group nct6775_in_template_group = {
1734 .templates = nct6775_attributes_in_template,
1735 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001736};
1737
1738static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001739show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1740{
1741 struct nct6775_data *data = nct6775_update_device(dev);
1742 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1743 int nr = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001744
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001745 return sprintf(buf, "%d\n", data->rpm[nr]);
1746}
1747
1748static ssize_t
1749show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1750{
1751 struct nct6775_data *data = nct6775_update_device(dev);
1752 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1753 int nr = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001754
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001755 return sprintf(buf, "%d\n",
1756 data->fan_from_reg_min(data->fan_min[nr],
1757 data->fan_div[nr]));
1758}
1759
1760static ssize_t
1761show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1762{
1763 struct nct6775_data *data = nct6775_update_device(dev);
1764 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1765 int nr = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001766
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001767 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1768}
1769
1770static ssize_t
1771store_fan_min(struct device *dev, struct device_attribute *attr,
1772 const char *buf, size_t count)
1773{
1774 struct nct6775_data *data = dev_get_drvdata(dev);
1775 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1776 int nr = sattr->index;
1777 unsigned long val;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001778 unsigned int reg;
1779 u8 new_div;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001780 int err;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001781
1782 err = kstrtoul(buf, 10, &val);
1783 if (err < 0)
1784 return err;
1785
1786 mutex_lock(&data->update_lock);
1787 if (!data->has_fan_div) {
1788 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1789 if (!val) {
1790 val = 0xff1f;
1791 } else {
1792 if (val > 1350000U)
1793 val = 135000U;
1794 val = 1350000U / val;
1795 val = (val & 0x1f) | ((val << 3) & 0xff00);
1796 }
1797 data->fan_min[nr] = val;
1798 goto write_min; /* Leave fan divider alone */
1799 }
1800 if (!val) {
1801 /* No min limit, alarm disabled */
1802 data->fan_min[nr] = 255;
1803 new_div = data->fan_div[nr]; /* No change */
1804 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1805 goto write_div;
1806 }
1807 reg = 1350000U / val;
1808 if (reg >= 128 * 255) {
1809 /*
1810 * Speed below this value cannot possibly be represented,
1811 * even with the highest divider (128)
1812 */
1813 data->fan_min[nr] = 254;
1814 new_div = 7; /* 128 == (1 << 7) */
1815 dev_warn(dev,
1816 "fan%u low limit %lu below minimum %u, set to minimum\n",
1817 nr + 1, val, data->fan_from_reg_min(254, 7));
1818 } else if (!reg) {
1819 /*
1820 * Speed above this value cannot possibly be represented,
1821 * even with the lowest divider (1)
1822 */
1823 data->fan_min[nr] = 1;
1824 new_div = 0; /* 1 == (1 << 0) */
1825 dev_warn(dev,
1826 "fan%u low limit %lu above maximum %u, set to maximum\n",
1827 nr + 1, val, data->fan_from_reg_min(1, 0));
1828 } else {
1829 /*
1830 * Automatically pick the best divider, i.e. the one such
1831 * that the min limit will correspond to a register value
1832 * in the 96..192 range
1833 */
1834 new_div = 0;
1835 while (reg > 192 && new_div < 7) {
1836 reg >>= 1;
1837 new_div++;
1838 }
1839 data->fan_min[nr] = reg;
1840 }
1841
1842write_div:
1843 /*
1844 * Write both the fan clock divider (if it changed) and the new
1845 * fan min (unconditionally)
1846 */
1847 if (new_div != data->fan_div[nr]) {
1848 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1849 nr + 1, div_from_reg(data->fan_div[nr]),
1850 div_from_reg(new_div));
1851 data->fan_div[nr] = new_div;
1852 nct6775_write_fan_div_common(data, nr);
1853 /* Give the chip time to sample a new speed value */
1854 data->last_updated = jiffies;
1855 }
1856
1857write_min:
1858 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1859 mutex_unlock(&data->update_lock);
1860
1861 return count;
1862}
1863
Guenter Roeck5c25d952012-12-11 07:29:06 -08001864static ssize_t
1865show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1866{
1867 struct nct6775_data *data = nct6775_update_device(dev);
1868 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1869 int p = data->fan_pulses[sattr->index];
1870
1871 return sprintf(buf, "%d\n", p ? : 4);
1872}
1873
1874static ssize_t
1875store_fan_pulses(struct device *dev, struct device_attribute *attr,
1876 const char *buf, size_t count)
1877{
1878 struct nct6775_data *data = dev_get_drvdata(dev);
1879 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1880 int nr = sattr->index;
1881 unsigned long val;
1882 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001883 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001884
1885 err = kstrtoul(buf, 10, &val);
1886 if (err < 0)
1887 return err;
1888
1889 if (val > 4)
1890 return -EINVAL;
1891
1892 mutex_lock(&data->update_lock);
1893 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001894 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1895 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1896 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1897 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001898 mutex_unlock(&data->update_lock);
1899
1900 return count;
1901}
1902
Guenter Roeckf73cf632013-03-18 09:22:50 -07001903static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1904 struct attribute *attr, int index)
1905{
1906 struct device *dev = container_of(kobj, struct device, kobj);
1907 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001908 int fan = index / 6; /* fan index */
1909 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001910
1911 if (!(data->has_fan & (1 << fan)))
1912 return 0;
1913
1914 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1915 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001916 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001917 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001918 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1919 return 0;
1920 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001921 return 0;
1922
1923 return attr->mode;
1924}
1925
1926SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1927SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1928 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001929SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1930 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001931SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1932 store_fan_pulses, 0);
1933SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1934 store_fan_min, 0);
1935SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1936
1937/*
1938 * nct6775_fan_is_visible uses the index into the following array
1939 * to determine if attributes should be created or not.
1940 * Any change in order or content must be matched.
1941 */
1942static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1943 &sensor_dev_template_fan_input,
1944 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001945 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001946 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001947 &sensor_dev_template_fan_min, /* 4 */
1948 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001949 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001950};
1951
Guenter Roeckf73cf632013-03-18 09:22:50 -07001952static struct sensor_template_group nct6775_fan_template_group = {
1953 .templates = nct6775_attributes_fan_template,
1954 .is_visible = nct6775_fan_is_visible,
1955 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001956};
1957
1958static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001959show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1960{
1961 struct nct6775_data *data = nct6775_update_device(dev);
1962 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1963 int nr = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08001964
Guenter Roeckaa136e52012-12-04 03:26:05 -08001965 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1966}
1967
1968static ssize_t
1969show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1970{
1971 struct nct6775_data *data = nct6775_update_device(dev);
1972 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1973 int nr = sattr->nr;
1974 int index = sattr->index;
1975
1976 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1977}
1978
1979static ssize_t
1980store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1981 size_t count)
1982{
1983 struct nct6775_data *data = dev_get_drvdata(dev);
1984 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1985 int nr = sattr->nr;
1986 int index = sattr->index;
1987 int err;
1988 long val;
1989
1990 err = kstrtol(buf, 10, &val);
1991 if (err < 0)
1992 return err;
1993
1994 mutex_lock(&data->update_lock);
1995 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1996 nct6775_write_temp(data, data->reg_temp[index][nr],
1997 data->temp[index][nr]);
1998 mutex_unlock(&data->update_lock);
1999 return count;
2000}
2001
2002static ssize_t
2003show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
2004{
2005 struct nct6775_data *data = nct6775_update_device(dev);
2006 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2007
2008 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
2009}
2010
2011static ssize_t
2012store_temp_offset(struct device *dev, struct device_attribute *attr,
2013 const char *buf, size_t count)
2014{
2015 struct nct6775_data *data = dev_get_drvdata(dev);
2016 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2017 int nr = sattr->index;
2018 long val;
2019 int err;
2020
2021 err = kstrtol(buf, 10, &val);
2022 if (err < 0)
2023 return err;
2024
2025 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
2026
2027 mutex_lock(&data->update_lock);
2028 data->temp_offset[nr] = val;
2029 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
2030 mutex_unlock(&data->update_lock);
2031
2032 return count;
2033}
2034
2035static ssize_t
2036show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2037{
2038 struct nct6775_data *data = nct6775_update_device(dev);
2039 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2040 int nr = sattr->index;
Guenter Roeck9cd892b2014-11-16 10:00:06 -08002041
Guenter Roeckaa136e52012-12-04 03:26:05 -08002042 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2043}
2044
2045static ssize_t
2046store_temp_type(struct device *dev, struct device_attribute *attr,
2047 const char *buf, size_t count)
2048{
2049 struct nct6775_data *data = nct6775_update_device(dev);
2050 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2051 int nr = sattr->index;
2052 unsigned long val;
2053 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002054 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002055
2056 err = kstrtoul(buf, 10, &val);
2057 if (err < 0)
2058 return err;
2059
2060 if (val != 1 && val != 3 && val != 4)
2061 return -EINVAL;
2062
2063 mutex_lock(&data->update_lock);
2064
2065 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002066 vbit = 0x02 << nr;
2067 dbit = data->DIODE_MASK << nr;
2068 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2069 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002070 switch (val) {
2071 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002072 vbat |= vbit;
2073 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002074 break;
2075 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002076 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002077 break;
2078 case 4: /* thermistor */
2079 break;
2080 }
2081 nct6775_write_value(data, data->REG_VBAT, vbat);
2082 nct6775_write_value(data, data->REG_DIODE, diode);
2083
2084 mutex_unlock(&data->update_lock);
2085 return count;
2086}
2087
Guenter Roeckf73cf632013-03-18 09:22:50 -07002088static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2089 struct attribute *attr, int index)
2090{
2091 struct device *dev = container_of(kobj, struct device, kobj);
2092 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002093 int temp = index / 10; /* temp index */
2094 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002095
2096 if (!(data->have_temp & (1 << temp)))
2097 return 0;
2098
2099 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2100 return 0; /* alarm */
2101
Guenter Roeck30846992013-06-24 22:21:59 -07002102 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2103 return 0; /* beep */
2104
2105 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002106 return 0;
2107
Guenter Roeck30846992013-06-24 22:21:59 -07002108 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002109 return 0;
2110
Guenter Roeck30846992013-06-24 22:21:59 -07002111 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002112 return 0;
2113
Guenter Roeck30846992013-06-24 22:21:59 -07002114 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002115 return 0;
2116
2117 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002118 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002119 return 0;
2120
2121 return attr->mode;
2122}
2123
2124SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2125SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2126SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2127 store_temp, 0, 1);
2128SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2129 show_temp, store_temp, 0, 2);
2130SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2131 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002132SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2133 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002134SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2135 show_temp_offset, store_temp_offset, 0);
2136SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2137 store_temp_type, 0);
2138SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002139SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2140 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002141
2142/*
2143 * nct6775_temp_is_visible uses the index into the following array
2144 * to determine if attributes should be created or not.
2145 * Any change in order or content must be matched.
2146 */
2147static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2148 &sensor_dev_template_temp_input,
2149 &sensor_dev_template_temp_label,
2150 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002151 &sensor_dev_template_temp_beep, /* 3 */
2152 &sensor_dev_template_temp_max, /* 4 */
2153 &sensor_dev_template_temp_max_hyst, /* 5 */
2154 &sensor_dev_template_temp_crit, /* 6 */
2155 &sensor_dev_template_temp_lcrit, /* 7 */
2156 &sensor_dev_template_temp_offset, /* 8 */
2157 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002158 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002159};
2160
Guenter Roeckf73cf632013-03-18 09:22:50 -07002161static struct sensor_template_group nct6775_temp_template_group = {
2162 .templates = nct6775_attributes_temp_template,
2163 .is_visible = nct6775_temp_is_visible,
2164 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002165};
2166
Guenter Roeckaa136e52012-12-04 03:26:05 -08002167static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002168show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2169{
2170 struct nct6775_data *data = nct6775_update_device(dev);
2171 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2172
2173 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2174}
2175
2176static ssize_t
2177store_pwm_mode(struct device *dev, struct device_attribute *attr,
2178 const char *buf, size_t count)
2179{
2180 struct nct6775_data *data = dev_get_drvdata(dev);
2181 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2182 int nr = sattr->index;
2183 unsigned long val;
2184 int err;
2185 u8 reg;
2186
2187 err = kstrtoul(buf, 10, &val);
2188 if (err < 0)
2189 return err;
2190
2191 if (val > 1)
2192 return -EINVAL;
2193
2194 /* Setting DC mode is not supported for all chips/channels */
2195 if (data->REG_PWM_MODE[nr] == 0) {
2196 if (val)
2197 return -EINVAL;
2198 return count;
2199 }
2200
2201 mutex_lock(&data->update_lock);
2202 data->pwm_mode[nr] = val;
2203 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2204 reg &= ~data->PWM_MODE_MASK[nr];
2205 if (val)
2206 reg |= data->PWM_MODE_MASK[nr];
2207 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2208 mutex_unlock(&data->update_lock);
2209 return count;
2210}
2211
2212static ssize_t
2213show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2214{
2215 struct nct6775_data *data = nct6775_update_device(dev);
2216 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2217 int nr = sattr->nr;
2218 int index = sattr->index;
2219 int pwm;
2220
2221 /*
2222 * For automatic fan control modes, show current pwm readings.
2223 * Otherwise, show the configured value.
2224 */
2225 if (index == 0 && data->pwm_enable[nr] > manual)
2226 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2227 else
2228 pwm = data->pwm[index][nr];
2229
2230 return sprintf(buf, "%d\n", pwm);
2231}
2232
2233static ssize_t
2234store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2235 size_t count)
2236{
2237 struct nct6775_data *data = dev_get_drvdata(dev);
2238 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2239 int nr = sattr->nr;
2240 int index = sattr->index;
2241 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002242 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2243 int maxval[7]
2244 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002245 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002246 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002247
2248 err = kstrtoul(buf, 10, &val);
2249 if (err < 0)
2250 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002251 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002252
2253 mutex_lock(&data->update_lock);
2254 data->pwm[index][nr] = val;
2255 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002256 if (index == 2) { /* floor: disable if val == 0 */
2257 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2258 reg &= 0x7f;
2259 if (val)
2260 reg |= 0x80;
2261 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2262 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002263 mutex_unlock(&data->update_lock);
2264 return count;
2265}
2266
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002267/* Returns 0 if OK, -EINVAL otherwise */
2268static int check_trip_points(struct nct6775_data *data, int nr)
2269{
2270 int i;
2271
2272 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2273 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2274 return -EINVAL;
2275 }
2276 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2277 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2278 return -EINVAL;
2279 }
2280 /* validate critical temperature and pwm if enabled (pwm > 0) */
2281 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2282 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2283 data->auto_temp[nr][data->auto_pwm_num] ||
2284 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2285 data->auto_pwm[nr][data->auto_pwm_num])
2286 return -EINVAL;
2287 }
2288 return 0;
2289}
2290
2291static void pwm_update_registers(struct nct6775_data *data, int nr)
2292{
2293 u8 reg;
2294
2295 switch (data->pwm_enable[nr]) {
2296 case off:
2297 case manual:
2298 break;
2299 case speed_cruise:
2300 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2301 reg = (reg & ~data->tolerance_mask) |
2302 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2303 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2304 nct6775_write_value(data, data->REG_TARGET[nr],
2305 data->target_speed[nr] & 0xff);
2306 if (data->REG_TOLERANCE_H) {
2307 reg = (data->target_speed[nr] >> 8) & 0x0f;
2308 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2309 nct6775_write_value(data,
2310 data->REG_TOLERANCE_H[nr],
2311 reg);
2312 }
2313 break;
2314 case thermal_cruise:
2315 nct6775_write_value(data, data->REG_TARGET[nr],
2316 data->target_temp[nr]);
2317 /* intentional */
2318 default:
2319 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2320 reg = (reg & ~data->tolerance_mask) |
2321 data->temp_tolerance[0][nr];
2322 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2323 break;
2324 }
2325}
2326
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002327static ssize_t
2328show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2329{
2330 struct nct6775_data *data = nct6775_update_device(dev);
2331 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2332
2333 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2334}
2335
2336static ssize_t
2337store_pwm_enable(struct device *dev, struct device_attribute *attr,
2338 const char *buf, size_t count)
2339{
2340 struct nct6775_data *data = dev_get_drvdata(dev);
2341 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2342 int nr = sattr->index;
2343 unsigned long val;
2344 int err;
2345 u16 reg;
2346
2347 err = kstrtoul(buf, 10, &val);
2348 if (err < 0)
2349 return err;
2350
2351 if (val > sf4)
2352 return -EINVAL;
2353
2354 if (val == sf3 && data->kind != nct6775)
2355 return -EINVAL;
2356
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002357 if (val == sf4 && check_trip_points(data, nr)) {
2358 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2359 dev_err(dev, "Adjust trip points and try again\n");
2360 return -EINVAL;
2361 }
2362
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002363 mutex_lock(&data->update_lock);
2364 data->pwm_enable[nr] = val;
2365 if (val == off) {
2366 /*
2367 * turn off pwm control: select manual mode, set pwm to maximum
2368 */
2369 data->pwm[0][nr] = 255;
2370 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2371 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002372 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002373 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2374 reg &= 0x0f;
2375 reg |= pwm_enable_to_reg(val) << 4;
2376 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2377 mutex_unlock(&data->update_lock);
2378 return count;
2379}
2380
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002381static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002382show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002383{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002384 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002385
2386 for (i = 0; i < NUM_TEMP; i++) {
2387 if (!(data->have_temp & (1 << i)))
2388 continue;
2389 if (src == data->temp_src[i]) {
2390 sel = i + 1;
2391 break;
2392 }
2393 }
2394
2395 return sprintf(buf, "%d\n", sel);
2396}
2397
2398static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002399show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2400{
2401 struct nct6775_data *data = nct6775_update_device(dev);
2402 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2403 int index = sattr->index;
2404
2405 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2406}
2407
2408static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002409store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2410 const char *buf, size_t count)
2411{
2412 struct nct6775_data *data = nct6775_update_device(dev);
2413 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2414 int nr = sattr->index;
2415 unsigned long val;
2416 int err, reg, src;
2417
2418 err = kstrtoul(buf, 10, &val);
2419 if (err < 0)
2420 return err;
2421 if (val == 0 || val > NUM_TEMP)
2422 return -EINVAL;
2423 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2424 return -EINVAL;
2425
2426 mutex_lock(&data->update_lock);
2427 src = data->temp_src[val - 1];
2428 data->pwm_temp_sel[nr] = src;
2429 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2430 reg &= 0xe0;
2431 reg |= src;
2432 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2433 mutex_unlock(&data->update_lock);
2434
2435 return count;
2436}
2437
2438static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002439show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2440 char *buf)
2441{
2442 struct nct6775_data *data = nct6775_update_device(dev);
2443 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2444 int index = sattr->index;
2445
2446 return show_pwm_temp_sel_common(data, buf,
2447 data->pwm_weight_temp_sel[index]);
2448}
2449
2450static ssize_t
2451store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2452 const char *buf, size_t count)
2453{
2454 struct nct6775_data *data = nct6775_update_device(dev);
2455 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2456 int nr = sattr->index;
2457 unsigned long val;
2458 int err, reg, src;
2459
2460 err = kstrtoul(buf, 10, &val);
2461 if (err < 0)
2462 return err;
2463 if (val > NUM_TEMP)
2464 return -EINVAL;
2465 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2466 !data->temp_src[val - 1]))
2467 return -EINVAL;
2468
2469 mutex_lock(&data->update_lock);
2470 if (val) {
2471 src = data->temp_src[val - 1];
2472 data->pwm_weight_temp_sel[nr] = src;
2473 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2474 reg &= 0xe0;
2475 reg |= (src | 0x80);
2476 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2477 } else {
2478 data->pwm_weight_temp_sel[nr] = 0;
2479 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2480 reg &= 0x7f;
2481 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2482 }
2483 mutex_unlock(&data->update_lock);
2484
2485 return count;
2486}
2487
2488static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002489show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2490{
2491 struct nct6775_data *data = nct6775_update_device(dev);
2492 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2493
2494 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2495}
2496
2497static ssize_t
2498store_target_temp(struct device *dev, struct device_attribute *attr,
2499 const char *buf, size_t count)
2500{
2501 struct nct6775_data *data = dev_get_drvdata(dev);
2502 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2503 int nr = sattr->index;
2504 unsigned long val;
2505 int err;
2506
2507 err = kstrtoul(buf, 10, &val);
2508 if (err < 0)
2509 return err;
2510
2511 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2512 data->target_temp_mask);
2513
2514 mutex_lock(&data->update_lock);
2515 data->target_temp[nr] = val;
2516 pwm_update_registers(data, nr);
2517 mutex_unlock(&data->update_lock);
2518 return count;
2519}
2520
2521static ssize_t
2522show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2523{
2524 struct nct6775_data *data = nct6775_update_device(dev);
2525 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2526 int nr = sattr->index;
2527
2528 return sprintf(buf, "%d\n",
2529 fan_from_reg16(data->target_speed[nr],
2530 data->fan_div[nr]));
2531}
2532
2533static ssize_t
2534store_target_speed(struct device *dev, struct device_attribute *attr,
2535 const char *buf, size_t count)
2536{
2537 struct nct6775_data *data = dev_get_drvdata(dev);
2538 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2539 int nr = sattr->index;
2540 unsigned long val;
2541 int err;
2542 u16 speed;
2543
2544 err = kstrtoul(buf, 10, &val);
2545 if (err < 0)
2546 return err;
2547
2548 val = clamp_val(val, 0, 1350000U);
2549 speed = fan_to_reg(val, data->fan_div[nr]);
2550
2551 mutex_lock(&data->update_lock);
2552 data->target_speed[nr] = speed;
2553 pwm_update_registers(data, nr);
2554 mutex_unlock(&data->update_lock);
2555 return count;
2556}
2557
2558static ssize_t
2559show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2560 char *buf)
2561{
2562 struct nct6775_data *data = nct6775_update_device(dev);
2563 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2564 int nr = sattr->nr;
2565 int index = sattr->index;
2566
2567 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2568}
2569
2570static ssize_t
2571store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2572 const char *buf, size_t count)
2573{
2574 struct nct6775_data *data = dev_get_drvdata(dev);
2575 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2576 int nr = sattr->nr;
2577 int index = sattr->index;
2578 unsigned long val;
2579 int err;
2580
2581 err = kstrtoul(buf, 10, &val);
2582 if (err < 0)
2583 return err;
2584
2585 /* Limit tolerance as needed */
2586 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2587
2588 mutex_lock(&data->update_lock);
2589 data->temp_tolerance[index][nr] = val;
2590 if (index)
2591 pwm_update_registers(data, nr);
2592 else
2593 nct6775_write_value(data,
2594 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2595 val);
2596 mutex_unlock(&data->update_lock);
2597 return count;
2598}
2599
2600/*
2601 * Fan speed tolerance is a tricky beast, since the associated register is
2602 * a tick counter, but the value is reported and configured as rpm.
2603 * Compute resulting low and high rpm values and report the difference.
2604 */
2605static ssize_t
2606show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2607 char *buf)
2608{
2609 struct nct6775_data *data = nct6775_update_device(dev);
2610 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2611 int nr = sattr->index;
2612 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2613 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2614 int tolerance;
2615
2616 if (low <= 0)
2617 low = 1;
2618 if (high > 0xffff)
2619 high = 0xffff;
2620 if (high < low)
2621 high = low;
2622
2623 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2624 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2625
2626 return sprintf(buf, "%d\n", tolerance);
2627}
2628
2629static ssize_t
2630store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2631 const char *buf, size_t count)
2632{
2633 struct nct6775_data *data = dev_get_drvdata(dev);
2634 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2635 int nr = sattr->index;
2636 unsigned long val;
2637 int err;
2638 int low, high;
2639
2640 err = kstrtoul(buf, 10, &val);
2641 if (err < 0)
2642 return err;
2643
2644 high = fan_from_reg16(data->target_speed[nr],
2645 data->fan_div[nr]) + val;
2646 low = fan_from_reg16(data->target_speed[nr],
2647 data->fan_div[nr]) - val;
2648 if (low <= 0)
2649 low = 1;
2650 if (high < low)
2651 high = low;
2652
2653 val = (fan_to_reg(low, data->fan_div[nr]) -
2654 fan_to_reg(high, data->fan_div[nr])) / 2;
2655
2656 /* Limit tolerance as needed */
2657 val = clamp_val(val, 0, data->speed_tolerance_limit);
2658
2659 mutex_lock(&data->update_lock);
2660 data->target_speed_tolerance[nr] = val;
2661 pwm_update_registers(data, nr);
2662 mutex_unlock(&data->update_lock);
2663 return count;
2664}
2665
Guenter Roeckf73cf632013-03-18 09:22:50 -07002666SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2667SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2668 store_pwm_mode, 0);
2669SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2670 store_pwm_enable, 0);
2671SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2672 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2673SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2674 show_target_temp, store_target_temp, 0);
2675SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2676 show_target_speed, store_target_speed, 0);
2677SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2678 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002679
2680/* Smart Fan registers */
2681
2682static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002683show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2684{
2685 struct nct6775_data *data = nct6775_update_device(dev);
2686 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2687 int nr = sattr->nr;
2688 int index = sattr->index;
2689
2690 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2691}
2692
2693static ssize_t
2694store_weight_temp(struct device *dev, struct device_attribute *attr,
2695 const char *buf, size_t count)
2696{
2697 struct nct6775_data *data = dev_get_drvdata(dev);
2698 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2699 int nr = sattr->nr;
2700 int index = sattr->index;
2701 unsigned long val;
2702 int err;
2703
2704 err = kstrtoul(buf, 10, &val);
2705 if (err < 0)
2706 return err;
2707
2708 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2709
2710 mutex_lock(&data->update_lock);
2711 data->weight_temp[index][nr] = val;
2712 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2713 mutex_unlock(&data->update_lock);
2714 return count;
2715}
2716
Guenter Roeckf73cf632013-03-18 09:22:50 -07002717SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2718 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2719SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2720 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2721SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2722 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2723SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2724 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2725SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2726 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2727SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2728 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002729
2730static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002731show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2732{
2733 struct nct6775_data *data = nct6775_update_device(dev);
2734 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2735 int nr = sattr->nr;
2736 int index = sattr->index;
2737
2738 return sprintf(buf, "%d\n",
2739 step_time_from_reg(data->fan_time[index][nr],
2740 data->pwm_mode[nr]));
2741}
2742
2743static ssize_t
2744store_fan_time(struct device *dev, struct device_attribute *attr,
2745 const char *buf, size_t count)
2746{
2747 struct nct6775_data *data = dev_get_drvdata(dev);
2748 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2749 int nr = sattr->nr;
2750 int index = sattr->index;
2751 unsigned long val;
2752 int err;
2753
2754 err = kstrtoul(buf, 10, &val);
2755 if (err < 0)
2756 return err;
2757
2758 val = step_time_to_reg(val, data->pwm_mode[nr]);
2759 mutex_lock(&data->update_lock);
2760 data->fan_time[index][nr] = val;
2761 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2762 mutex_unlock(&data->update_lock);
2763 return count;
2764}
2765
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002766static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002767show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2768{
2769 struct nct6775_data *data = nct6775_update_device(dev);
2770 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2771
2772 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2773}
2774
2775static ssize_t
2776store_auto_pwm(struct device *dev, struct device_attribute *attr,
2777 const char *buf, size_t count)
2778{
2779 struct nct6775_data *data = dev_get_drvdata(dev);
2780 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2781 int nr = sattr->nr;
2782 int point = sattr->index;
2783 unsigned long val;
2784 int err;
2785 u8 reg;
2786
2787 err = kstrtoul(buf, 10, &val);
2788 if (err < 0)
2789 return err;
2790 if (val > 255)
2791 return -EINVAL;
2792
2793 if (point == data->auto_pwm_num) {
2794 if (data->kind != nct6775 && !val)
2795 return -EINVAL;
2796 if (data->kind != nct6779 && val)
2797 val = 0xff;
2798 }
2799
2800 mutex_lock(&data->update_lock);
2801 data->auto_pwm[nr][point] = val;
2802 if (point < data->auto_pwm_num) {
2803 nct6775_write_value(data,
2804 NCT6775_AUTO_PWM(data, nr, point),
2805 data->auto_pwm[nr][point]);
2806 } else {
2807 switch (data->kind) {
2808 case nct6775:
2809 /* disable if needed (pwm == 0) */
2810 reg = nct6775_read_value(data,
2811 NCT6775_REG_CRITICAL_ENAB[nr]);
2812 if (val)
2813 reg |= 0x02;
2814 else
2815 reg &= ~0x02;
2816 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2817 reg);
2818 break;
2819 case nct6776:
2820 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002821 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002822 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002823 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08002824 case nct6792:
Guenter Roeck6c009502012-07-01 08:23:15 -07002825 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002826 val);
2827 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002828 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002829 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002830 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002831 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002832 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002833 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002834 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002835 reg);
2836 break;
2837 }
2838 }
2839 mutex_unlock(&data->update_lock);
2840 return count;
2841}
2842
2843static ssize_t
2844show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2845{
2846 struct nct6775_data *data = nct6775_update_device(dev);
2847 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2848 int nr = sattr->nr;
2849 int point = sattr->index;
2850
2851 /*
2852 * We don't know for sure if the temperature is signed or unsigned.
2853 * Assume it is unsigned.
2854 */
2855 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2856}
2857
2858static ssize_t
2859store_auto_temp(struct device *dev, struct device_attribute *attr,
2860 const char *buf, size_t count)
2861{
2862 struct nct6775_data *data = dev_get_drvdata(dev);
2863 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2864 int nr = sattr->nr;
2865 int point = sattr->index;
2866 unsigned long val;
2867 int err;
2868
2869 err = kstrtoul(buf, 10, &val);
2870 if (err)
2871 return err;
2872 if (val > 255000)
2873 return -EINVAL;
2874
2875 mutex_lock(&data->update_lock);
2876 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2877 if (point < data->auto_pwm_num) {
2878 nct6775_write_value(data,
2879 NCT6775_AUTO_TEMP(data, nr, point),
2880 data->auto_temp[nr][point]);
2881 } else {
2882 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2883 data->auto_temp[nr][point]);
2884 }
2885 mutex_unlock(&data->update_lock);
2886 return count;
2887}
2888
Guenter Roeckf73cf632013-03-18 09:22:50 -07002889static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2890 struct attribute *attr, int index)
2891{
2892 struct device *dev = container_of(kobj, struct device, kobj);
2893 struct nct6775_data *data = dev_get_drvdata(dev);
2894 int pwm = index / 36; /* pwm index */
2895 int nr = index % 36; /* attribute index */
2896
2897 if (!(data->has_pwm & (1 << pwm)))
2898 return 0;
2899
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002900 if ((nr >= 14 && nr <= 18) || nr == 21) /* weight */
2901 if (!data->REG_WEIGHT_TEMP_SEL[pwm])
2902 return 0;
Guenter Roeckf73cf632013-03-18 09:22:50 -07002903 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2904 return 0;
2905 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2906 return 0;
2907 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2908 return 0;
2909
2910 if (nr >= 22 && nr <= 35) { /* auto point */
2911 int api = (nr - 22) / 2; /* auto point index */
2912
2913 if (api > data->auto_pwm_num)
2914 return 0;
2915 }
2916 return attr->mode;
2917}
2918
2919SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2920 show_fan_time, store_fan_time, 0, 0);
2921SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2922 show_fan_time, store_fan_time, 0, 1);
2923SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2924 show_fan_time, store_fan_time, 0, 2);
2925SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2926 store_pwm, 0, 1);
2927SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2928 store_pwm, 0, 2);
2929SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2930 show_temp_tolerance, store_temp_tolerance, 0, 0);
2931SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2932 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2933 0, 1);
2934
2935SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2936 0, 3);
2937
2938SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2939 store_pwm, 0, 4);
2940
2941SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2942 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2943SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2944 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2945
2946SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2947 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2948SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2949 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2950
2951SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2952 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2953SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2954 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2955
2956SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2957 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2958SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2959 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2960
2961SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2962 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2963SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2964 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2965
2966SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2967 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2968SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2969 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2970
2971SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2972 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2973SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2974 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2975
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002976/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002977 * nct6775_pwm_is_visible uses the index into the following array
2978 * to determine if attributes should be created or not.
2979 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002980 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002981static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2982 &sensor_dev_template_pwm,
2983 &sensor_dev_template_pwm_mode,
2984 &sensor_dev_template_pwm_enable,
2985 &sensor_dev_template_pwm_temp_sel,
2986 &sensor_dev_template_pwm_temp_tolerance,
2987 &sensor_dev_template_pwm_crit_temp_tolerance,
2988 &sensor_dev_template_pwm_target_temp,
2989 &sensor_dev_template_fan_target,
2990 &sensor_dev_template_fan_tolerance,
2991 &sensor_dev_template_pwm_stop_time,
2992 &sensor_dev_template_pwm_step_up_time,
2993 &sensor_dev_template_pwm_step_down_time,
2994 &sensor_dev_template_pwm_start,
2995 &sensor_dev_template_pwm_floor,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002996 &sensor_dev_template_pwm_weight_temp_sel, /* 14 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002997 &sensor_dev_template_pwm_weight_temp_step,
2998 &sensor_dev_template_pwm_weight_temp_step_tol,
2999 &sensor_dev_template_pwm_weight_temp_step_base,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003000 &sensor_dev_template_pwm_weight_duty_step, /* 18 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003001 &sensor_dev_template_pwm_max, /* 19 */
3002 &sensor_dev_template_pwm_step, /* 20 */
3003 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
3004 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
3005 &sensor_dev_template_pwm_auto_point1_temp,
3006 &sensor_dev_template_pwm_auto_point2_pwm,
3007 &sensor_dev_template_pwm_auto_point2_temp,
3008 &sensor_dev_template_pwm_auto_point3_pwm,
3009 &sensor_dev_template_pwm_auto_point3_temp,
3010 &sensor_dev_template_pwm_auto_point4_pwm,
3011 &sensor_dev_template_pwm_auto_point4_temp,
3012 &sensor_dev_template_pwm_auto_point5_pwm,
3013 &sensor_dev_template_pwm_auto_point5_temp,
3014 &sensor_dev_template_pwm_auto_point6_pwm,
3015 &sensor_dev_template_pwm_auto_point6_temp,
3016 &sensor_dev_template_pwm_auto_point7_pwm,
3017 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003018
Guenter Roeckf73cf632013-03-18 09:22:50 -07003019 NULL
3020};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003021
Guenter Roeckf73cf632013-03-18 09:22:50 -07003022static struct sensor_template_group nct6775_pwm_template_group = {
3023 .templates = nct6775_attributes_pwm_template,
3024 .is_visible = nct6775_pwm_is_visible,
3025 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003026};
3027
3028static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003029show_vid(struct device *dev, struct device_attribute *attr, char *buf)
3030{
3031 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck9cd892b2014-11-16 10:00:06 -08003032
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003033 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3034}
3035
3036static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3037
Guenter Roecka6bd5872012-12-04 03:13:34 -08003038/* Case open detection */
3039
3040static ssize_t
3041clear_caseopen(struct device *dev, struct device_attribute *attr,
3042 const char *buf, size_t count)
3043{
3044 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003045 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3046 unsigned long val;
3047 u8 reg;
3048 int ret;
3049
3050 if (kstrtoul(buf, 10, &val) || val != 0)
3051 return -EINVAL;
3052
3053 mutex_lock(&data->update_lock);
3054
3055 /*
3056 * Use CR registers to clear caseopen status.
3057 * The CR registers are the same for all chips, and not all chips
3058 * support clearing the caseopen status through "regular" registers.
3059 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003060 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003061 if (ret) {
3062 count = ret;
3063 goto error;
3064 }
3065
Guenter Roeckdf612d52013-07-08 13:15:04 -07003066 superio_select(data->sioreg, NCT6775_LD_ACPI);
3067 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003068 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003069 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003070 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003071 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3072 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003073
3074 data->valid = false; /* Force cache refresh */
3075error:
3076 mutex_unlock(&data->update_lock);
3077 return count;
3078}
3079
Guenter Roeckf73cf632013-03-18 09:22:50 -07003080static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3081 clear_caseopen, INTRUSION_ALARM_BASE);
3082static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3083 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003084static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3085 store_beep, INTRUSION_ALARM_BASE);
3086static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3087 store_beep, INTRUSION_ALARM_BASE + 1);
3088static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3089 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003090
3091static umode_t nct6775_other_is_visible(struct kobject *kobj,
3092 struct attribute *attr, int index)
3093{
3094 struct device *dev = container_of(kobj, struct device, kobj);
3095 struct nct6775_data *data = dev_get_drvdata(dev);
3096
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003097 if (index == 0 && !data->have_vid)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003098 return 0;
3099
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003100 if (index == 1 || index == 2) {
3101 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003102 return 0;
3103 }
3104
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003105 if (index == 3 || index == 4) {
3106 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
Guenter Roeck30846992013-06-24 22:21:59 -07003107 return 0;
3108 }
3109
Guenter Roeckf73cf632013-03-18 09:22:50 -07003110 return attr->mode;
3111}
3112
3113/*
3114 * nct6775_other_is_visible uses the index into the following array
3115 * to determine if attributes should be created or not.
3116 * Any change in order or content must be matched.
3117 */
3118static struct attribute *nct6775_attributes_other[] = {
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003119 &dev_attr_cpu0_vid.attr, /* 0 */
3120 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
3121 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
3122 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
3123 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
3124 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003125
3126 NULL
3127};
3128
3129static const struct attribute_group nct6775_group_other = {
3130 .attrs = nct6775_attributes_other,
3131 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003132};
3133
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003134static inline void nct6775_init_device(struct nct6775_data *data)
3135{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003136 int i;
3137 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003138
3139 /* Start monitoring if needed */
3140 if (data->REG_CONFIG) {
3141 tmp = nct6775_read_value(data, data->REG_CONFIG);
3142 if (!(tmp & 0x01))
3143 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3144 }
3145
Guenter Roeckaa136e52012-12-04 03:26:05 -08003146 /* Enable temperature sensors if needed */
3147 for (i = 0; i < NUM_TEMP; i++) {
3148 if (!(data->have_temp & (1 << i)))
3149 continue;
3150 if (!data->reg_temp_config[i])
3151 continue;
3152 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3153 if (tmp & 0x01)
3154 nct6775_write_value(data, data->reg_temp_config[i],
3155 tmp & 0xfe);
3156 }
3157
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003158 /* Enable VBAT monitoring if needed */
3159 tmp = nct6775_read_value(data, data->REG_VBAT);
3160 if (!(tmp & 0x01))
3161 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003162
3163 diode = nct6775_read_value(data, data->REG_DIODE);
3164
3165 for (i = 0; i < data->temp_fixed_num; i++) {
3166 if (!(data->have_temp_fixed & (1 << i)))
3167 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003168 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3169 data->temp_type[i]
3170 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003171 else /* thermistor */
3172 data->temp_type[i] = 4;
3173 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003174}
3175
Guenter Roeckf73cf632013-03-18 09:22:50 -07003176static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003177nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003178{
David Bartley578ab5f2013-06-24 22:28:28 -07003179 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3180 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003181 int sioreg = data->sioreg;
3182 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003183
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08003184 /* Store SIO_REG_ENABLE for use during resume */
3185 superio_select(sioreg, NCT6775_LD_HWM);
3186 data->sio_reg_enable = superio_inb(sioreg, SIO_REG_ENABLE);
3187
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003188 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3189 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003190 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003191
3192 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003193 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003194
3195 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003196 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003197 fan4min = false;
3198 fan5pin = false;
3199 fan6pin = false;
3200 pwm4pin = false;
3201 pwm5pin = false;
3202 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003203 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003204 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck25cdd992015-02-06 18:55:36 -08003205 const char *board_vendor, *board_name;
3206
3207 board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
3208 board_name = dmi_get_system_info(DMI_BOARD_NAME);
3209
3210 if (board_name && board_vendor &&
3211 !strcmp(board_vendor, "ASRock")) {
3212 /*
3213 * Auxiliary fan monitoring is not enabled on ASRock
3214 * Z77 Pro4-M if booted in UEFI Ultra-FastBoot mode.
3215 * Observed with BIOS version 2.00.
3216 */
3217 if (!strcmp(board_name, "Z77 Pro4-M")) {
3218 if ((data->sio_reg_enable & 0xe0) != 0xe0) {
3219 data->sio_reg_enable |= 0xe0;
3220 superio_outb(sioreg, SIO_REG_ENABLE,
3221 data->sio_reg_enable);
3222 }
3223 }
3224 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003225
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08003226 if (data->sio_reg_enable & 0x80)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003227 fan3pin = gpok;
3228 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003229 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003230
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08003231 if (data->sio_reg_enable & 0x40)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003232 fan4pin = gpok;
3233 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003234 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003235
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08003236 if (data->sio_reg_enable & 0x20)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003237 fan5pin = gpok;
3238 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003239 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003240
3241 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003242 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003243 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003244 pwm4pin = false;
3245 pwm5pin = false;
3246 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003247 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003248 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003249 fan3pin = !(regval & 0x80);
3250 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003251
3252 fan4pin = false;
3253 fan4min = false;
3254 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003255 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003256 pwm4pin = false;
3257 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003258 pwm6pin = false;
Guenter Roeck8aefb932014-11-16 09:50:04 -08003259 } else { /* NCT6779D, NCT6791D, or NCT6792D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003260 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003261
3262 fan3pin = !(regval & (1 << 5));
3263 fan4pin = !(regval & (1 << 6));
3264 fan5pin = !(regval & (1 << 7));
3265
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003266 pwm3pin = !(regval & (1 << 0));
3267 pwm4pin = !(regval & (1 << 1));
3268 pwm5pin = !(regval & (1 << 2));
3269
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003270 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003271
Guenter Roeck8aefb932014-11-16 09:50:04 -08003272 if (data->kind == nct6791 || data->kind == nct6792) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003273 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003274 fan6pin = (regval & (1 << 1));
3275 pwm6pin = (regval & (1 << 0));
3276 } else { /* NCT6779D */
3277 fan6pin = false;
3278 pwm6pin = false;
3279 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003280 }
3281
David Bartley578ab5f2013-06-24 22:28:28 -07003282 /* fan 1 and 2 (0x03) are always present */
3283 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3284 (fan5pin << 4) | (fan6pin << 5);
3285 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3286 (fan5pin << 4);
3287 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3288 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003289}
3290
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003291static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3292 int *available, int *mask)
3293{
3294 int i;
3295 u8 src;
3296
3297 for (i = 0; i < data->pwm_num && *available; i++) {
3298 int index;
3299
3300 if (!regp[i])
3301 continue;
3302 src = nct6775_read_value(data, regp[i]);
3303 src &= 0x1f;
3304 if (!src || (*mask & (1 << src)))
3305 continue;
3306 if (src >= data->temp_label_num ||
3307 !strlen(data->temp_label[src]))
3308 continue;
3309
3310 index = __ffs(*available);
3311 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3312 *available &= ~(1 << index);
3313 *mask |= 1 << src;
3314 }
3315}
3316
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003317static int nct6775_probe(struct platform_device *pdev)
3318{
3319 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003320 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003321 struct nct6775_data *data;
3322 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003323 int i, s, err = 0;
3324 int src, mask, available;
3325 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003326 const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003327 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003328 int num_reg_temp, num_reg_temp_mon;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003329 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003330 struct attribute_group *group;
Guenter Roecka150d952013-07-11 22:55:22 -07003331 struct device *hwmon_dev;
Axel Lin55bdee62014-07-24 08:59:34 +08003332 int num_attr_groups = 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003333
3334 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3335 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3336 DRVNAME))
3337 return -EBUSY;
3338
3339 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3340 GFP_KERNEL);
3341 if (!data)
3342 return -ENOMEM;
3343
3344 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003345 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003346 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003347 mutex_init(&data->update_lock);
3348 data->name = nct6775_device_names[data->kind];
3349 data->bank = 0xff; /* Force initial bank selection */
3350 platform_set_drvdata(pdev, data);
3351
3352 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003353 case nct6106:
3354 data->in_num = 9;
3355 data->pwm_num = 3;
3356 data->auto_pwm_num = 4;
3357 data->temp_fixed_num = 3;
3358 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003359 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003360
3361 data->fan_from_reg = fan_from_reg13;
3362 data->fan_from_reg_min = fan_from_reg13;
3363
3364 data->temp_label = nct6776_temp_label;
3365 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3366
3367 data->REG_VBAT = NCT6106_REG_VBAT;
3368 data->REG_DIODE = NCT6106_REG_DIODE;
3369 data->DIODE_MASK = NCT6106_DIODE_MASK;
3370 data->REG_VIN = NCT6106_REG_IN;
3371 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3372 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3373 data->REG_TARGET = NCT6106_REG_TARGET;
3374 data->REG_FAN = NCT6106_REG_FAN;
3375 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3376 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3377 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3378 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3379 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3380 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3381 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3382 data->REG_PWM[0] = NCT6106_REG_PWM;
3383 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3384 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3385 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3386 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3387 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3388 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3389 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3390 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3391 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3392 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3393 data->REG_CRITICAL_TEMP_TOLERANCE
3394 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3395 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3396 data->CRITICAL_PWM_ENABLE_MASK
3397 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3398 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3399 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3400 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3401 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3402 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3403 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3404 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3405 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3406 data->REG_ALARM = NCT6106_REG_ALARM;
3407 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003408 data->REG_BEEP = NCT6106_REG_BEEP;
3409 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003410
3411 reg_temp = NCT6106_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003412 reg_temp_mon = NCT6106_REG_TEMP_MON;
Guenter Roeck6c009502012-07-01 08:23:15 -07003413 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003414 num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
Guenter Roeck6c009502012-07-01 08:23:15 -07003415 reg_temp_over = NCT6106_REG_TEMP_OVER;
3416 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3417 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3418 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3419 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003420 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3421 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003422
3423 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003424 case nct6775:
3425 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003426 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003427 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003428 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003429 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003430 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003431 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003432
3433 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003434 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003435
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003436 data->fan_from_reg = fan_from_reg16;
3437 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003438 data->target_temp_mask = 0x7f;
3439 data->tolerance_mask = 0x0f;
3440 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003441
Guenter Roeckaa136e52012-12-04 03:26:05 -08003442 data->temp_label = nct6775_temp_label;
3443 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3444
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003445 data->REG_CONFIG = NCT6775_REG_CONFIG;
3446 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003447 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003448 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003449 data->REG_VIN = NCT6775_REG_IN;
3450 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3451 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003452 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003453 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003454 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003455 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003456 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003457 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003458 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3459 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3460 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003461 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003462 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3463 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3464 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3465 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003466 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003467 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3468 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3469 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003470 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3471 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3472 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3473 data->REG_CRITICAL_TEMP_TOLERANCE
3474 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003475 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3476 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003477 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003478 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3479 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3480 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3481 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003482 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003483 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003484
3485 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003486 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003487 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003488 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003489 reg_temp_over = NCT6775_REG_TEMP_OVER;
3490 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3491 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3492 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3493 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3494
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003495 break;
3496 case nct6776:
3497 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003498 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003499 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003500 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003501 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003502 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003503 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003504
3505 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003506 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003507
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003508 data->fan_from_reg = fan_from_reg13;
3509 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003510 data->target_temp_mask = 0xff;
3511 data->tolerance_mask = 0x07;
3512 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003513
Guenter Roeckaa136e52012-12-04 03:26:05 -08003514 data->temp_label = nct6776_temp_label;
3515 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3516
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003517 data->REG_CONFIG = NCT6775_REG_CONFIG;
3518 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003519 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003520 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003521 data->REG_VIN = NCT6775_REG_IN;
3522 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3523 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003524 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003525 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003526 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003527 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003528 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003529 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003530 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3531 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3532 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3533 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003534 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003535 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3536 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003537 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3538 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003539 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3540 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3541 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003542 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3543 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3544 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3545 data->REG_CRITICAL_TEMP_TOLERANCE
3546 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003547 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3548 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003549 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003550 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3551 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3552 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3553 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003554 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003555 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003556
3557 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003558 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003559 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003560 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003561 reg_temp_over = NCT6775_REG_TEMP_OVER;
3562 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3563 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3564 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3565 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3566
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003567 break;
3568 case nct6779:
3569 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003570 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003571 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003572 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003573 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003574 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003575 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003576
3577 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003578 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003579
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003580 data->fan_from_reg = fan_from_reg13;
3581 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003582 data->target_temp_mask = 0xff;
3583 data->tolerance_mask = 0x07;
3584 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003585
Guenter Roeckaa136e52012-12-04 03:26:05 -08003586 data->temp_label = nct6779_temp_label;
3587 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3588
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003589 data->REG_CONFIG = NCT6775_REG_CONFIG;
3590 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003591 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003592 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003593 data->REG_VIN = NCT6779_REG_IN;
3594 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3595 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003596 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003597 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003598 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003599 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003600 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003601 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003602 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3603 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3604 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3605 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003606 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003607 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3608 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003609 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3610 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003611 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3612 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3613 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003614 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3615 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3616 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3617 data->REG_CRITICAL_TEMP_TOLERANCE
3618 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003619 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3620 data->CRITICAL_PWM_ENABLE_MASK
3621 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3622 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003623 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3624 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003625 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003626 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3627 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3628 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3629 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003630 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003631 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003632
3633 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003634 reg_temp_mon = NCT6779_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003635 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003636 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003637 reg_temp_over = NCT6779_REG_TEMP_OVER;
3638 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3639 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3640 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3641 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3642
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003643 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003644 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003645 case nct6792:
David Bartley578ab5f2013-06-24 22:28:28 -07003646 data->in_num = 15;
3647 data->pwm_num = 6;
3648 data->auto_pwm_num = 4;
3649 data->has_fan_div = false;
3650 data->temp_fixed_num = 6;
3651 data->num_temp_alarms = 2;
3652 data->num_temp_beeps = 2;
3653
3654 data->ALARM_BITS = NCT6791_ALARM_BITS;
3655 data->BEEP_BITS = NCT6779_BEEP_BITS;
3656
3657 data->fan_from_reg = fan_from_reg13;
3658 data->fan_from_reg_min = fan_from_reg13;
3659 data->target_temp_mask = 0xff;
3660 data->tolerance_mask = 0x07;
3661 data->speed_tolerance_limit = 63;
3662
3663 data->temp_label = nct6779_temp_label;
3664 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3665
3666 data->REG_CONFIG = NCT6775_REG_CONFIG;
3667 data->REG_VBAT = NCT6775_REG_VBAT;
3668 data->REG_DIODE = NCT6775_REG_DIODE;
3669 data->DIODE_MASK = NCT6775_DIODE_MASK;
3670 data->REG_VIN = NCT6779_REG_IN;
3671 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3672 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3673 data->REG_TARGET = NCT6775_REG_TARGET;
3674 data->REG_FAN = NCT6779_REG_FAN;
3675 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3676 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3677 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3678 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3679 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3680 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3681 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3682 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3683 data->REG_PWM[0] = NCT6775_REG_PWM;
3684 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3685 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003686 data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
3687 data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003688 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3689 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3690 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3691 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3692 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3693 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3694 data->REG_CRITICAL_TEMP_TOLERANCE
3695 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3696 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3697 data->CRITICAL_PWM_ENABLE_MASK
3698 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3699 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3700 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3701 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3702 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003703 data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
3704 data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
3705 data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
3706 data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003707 data->REG_ALARM = NCT6791_REG_ALARM;
Guenter Roeck8aefb932014-11-16 09:50:04 -08003708 if (data->kind == nct6791)
3709 data->REG_BEEP = NCT6776_REG_BEEP;
3710 else
3711 data->REG_BEEP = NCT6792_REG_BEEP;
David Bartley578ab5f2013-06-24 22:28:28 -07003712
3713 reg_temp = NCT6779_REG_TEMP;
3714 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeck8aefb932014-11-16 09:50:04 -08003715 if (data->kind == nct6791) {
3716 reg_temp_mon = NCT6779_REG_TEMP_MON;
3717 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3718 } else {
3719 reg_temp_mon = NCT6792_REG_TEMP_MON;
3720 num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
3721 }
David Bartley578ab5f2013-06-24 22:28:28 -07003722 reg_temp_over = NCT6779_REG_TEMP_OVER;
3723 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3724 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3725 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3726 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3727
3728 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003729 default:
3730 return -ENODEV;
3731 }
3732 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003733 data->have_temp = 0;
3734
3735 /*
3736 * On some boards, not all available temperature sources are monitored,
3737 * even though some of the monitoring registers are unused.
3738 * Get list of unused monitoring registers, then detect if any fan
3739 * controls are configured to use unmonitored temperature sources.
3740 * If so, assign the unmonitored temperature sources to available
3741 * monitoring registers.
3742 */
3743 mask = 0;
3744 available = 0;
3745 for (i = 0; i < num_reg_temp; i++) {
3746 if (reg_temp[i] == 0)
3747 continue;
3748
3749 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3750 if (!src || (mask & (1 << src)))
3751 available |= 1 << i;
3752
3753 mask |= 1 << src;
3754 }
3755
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003756 /*
3757 * Now find unmonitored temperature registers and enable monitoring
3758 * if additional monitoring registers are available.
3759 */
3760 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3761 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3762
Guenter Roeckaa136e52012-12-04 03:26:05 -08003763 mask = 0;
3764 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3765 for (i = 0; i < num_reg_temp; i++) {
3766 if (reg_temp[i] == 0)
3767 continue;
3768
3769 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3770 if (!src || (mask & (1 << src)))
3771 continue;
3772
3773 if (src >= data->temp_label_num ||
3774 !strlen(data->temp_label[src])) {
3775 dev_info(dev,
3776 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3777 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3778 continue;
3779 }
3780
3781 mask |= 1 << src;
3782
3783 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3784 if (src <= data->temp_fixed_num) {
3785 data->have_temp |= 1 << (src - 1);
3786 data->have_temp_fixed |= 1 << (src - 1);
3787 data->reg_temp[0][src - 1] = reg_temp[i];
3788 data->reg_temp[1][src - 1] = reg_temp_over[i];
3789 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003790 if (reg_temp_crit_h && reg_temp_crit_h[i])
3791 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3792 else if (reg_temp_crit[src - 1])
3793 data->reg_temp[3][src - 1]
3794 = reg_temp_crit[src - 1];
3795 if (reg_temp_crit_l && reg_temp_crit_l[i])
3796 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003797 data->reg_temp_config[src - 1] = reg_temp_config[i];
3798 data->temp_src[src - 1] = src;
3799 continue;
3800 }
3801
3802 if (s >= NUM_TEMP)
3803 continue;
3804
3805 /* Use dynamic index for other sources */
3806 data->have_temp |= 1 << s;
3807 data->reg_temp[0][s] = reg_temp[i];
3808 data->reg_temp[1][s] = reg_temp_over[i];
3809 data->reg_temp[2][s] = reg_temp_hyst[i];
3810 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003811 if (reg_temp_crit_h && reg_temp_crit_h[i])
3812 data->reg_temp[3][s] = reg_temp_crit_h[i];
3813 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003814 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003815 if (reg_temp_crit_l && reg_temp_crit_l[i])
3816 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003817
3818 data->temp_src[s] = src;
3819 s++;
3820 }
3821
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003822 /*
3823 * Repeat with temperatures used for fan control.
3824 * This set of registers does not support limits.
3825 */
3826 for (i = 0; i < num_reg_temp_mon; i++) {
3827 if (reg_temp_mon[i] == 0)
3828 continue;
3829
3830 src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
3831 if (!src || (mask & (1 << src)))
3832 continue;
3833
3834 if (src >= data->temp_label_num ||
3835 !strlen(data->temp_label[src])) {
3836 dev_info(dev,
3837 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3838 src, i, data->REG_TEMP_SEL[i],
3839 reg_temp_mon[i]);
3840 continue;
3841 }
3842
3843 mask |= 1 << src;
3844
3845 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3846 if (src <= data->temp_fixed_num) {
3847 if (data->have_temp & (1 << (src - 1)))
3848 continue;
3849 data->have_temp |= 1 << (src - 1);
3850 data->have_temp_fixed |= 1 << (src - 1);
3851 data->reg_temp[0][src - 1] = reg_temp_mon[i];
3852 data->temp_src[src - 1] = src;
3853 continue;
3854 }
3855
3856 if (s >= NUM_TEMP)
3857 continue;
3858
3859 /* Use dynamic index for other sources */
3860 data->have_temp |= 1 << s;
3861 data->reg_temp[0][s] = reg_temp_mon[i];
3862 data->temp_src[s] = src;
3863 s++;
3864 }
3865
Guenter Roeckaa136e52012-12-04 03:26:05 -08003866#ifdef USE_ALTERNATE
3867 /*
3868 * Go through the list of alternate temp registers and enable
3869 * if possible.
3870 * The temperature is already monitored if the respective bit in <mask>
3871 * is set.
3872 */
3873 for (i = 0; i < data->temp_label_num - 1; i++) {
3874 if (!reg_temp_alternate[i])
3875 continue;
3876 if (mask & (1 << (i + 1)))
3877 continue;
3878 if (i < data->temp_fixed_num) {
3879 if (data->have_temp & (1 << i))
3880 continue;
3881 data->have_temp |= 1 << i;
3882 data->have_temp_fixed |= 1 << i;
3883 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003884 if (i < num_reg_temp) {
3885 data->reg_temp[1][i] = reg_temp_over[i];
3886 data->reg_temp[2][i] = reg_temp_hyst[i];
3887 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003888 data->temp_src[i] = i + 1;
3889 continue;
3890 }
3891
3892 if (s >= NUM_TEMP) /* Abort if no more space */
3893 break;
3894
3895 data->have_temp |= 1 << s;
3896 data->reg_temp[0][s] = reg_temp_alternate[i];
3897 data->temp_src[s] = i + 1;
3898 s++;
3899 }
3900#endif /* USE_ALTERNATE */
3901
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003902 /* Initialize the chip */
3903 nct6775_init_device(data);
3904
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003905 err = superio_enter(sio_data->sioreg);
3906 if (err)
3907 return err;
3908
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003909 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3910 switch (data->kind) {
3911 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003912 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003913 break;
3914 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003915 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003916 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003917 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003918 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003919 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003920 case nct6792:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003921 break;
3922 }
3923
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003924 /*
3925 * Read VID value
3926 * We can get the VID input values directly at logical device D 0xe3.
3927 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003928 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003929 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3930 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3931 data->vrm = vid_which_vrm();
3932 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003933
3934 if (fan_debounce) {
3935 u8 tmp;
3936
3937 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3938 tmp = superio_inb(sio_data->sioreg,
3939 NCT6775_REG_CR_FAN_DEBOUNCE);
3940 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003941 case nct6106:
3942 tmp |= 0xe0;
3943 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003944 case nct6775:
3945 tmp |= 0x1e;
3946 break;
3947 case nct6776:
3948 case nct6779:
3949 tmp |= 0x3e;
3950 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003951 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003952 case nct6792:
David Bartley578ab5f2013-06-24 22:28:28 -07003953 tmp |= 0x7e;
3954 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003955 }
3956 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3957 tmp);
3958 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3959 data->name);
3960 }
3961
Guenter Roeckdf612d52013-07-08 13:15:04 -07003962 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003963
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003964 superio_exit(sio_data->sioreg);
3965
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003966 /* Read fan clock dividers immediately */
3967 nct6775_init_fan_common(dev, data);
3968
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003969 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003970 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3971 data->pwm_num);
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003972 if (IS_ERR(group))
3973 return PTR_ERR(group);
3974
Axel Lin55bdee62014-07-24 08:59:34 +08003975 data->groups[num_attr_groups++] = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003976
Guenter Roeckf73cf632013-03-18 09:22:50 -07003977 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3978 fls(data->have_in));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003979 if (IS_ERR(group))
3980 return PTR_ERR(group);
3981
Axel Lin55bdee62014-07-24 08:59:34 +08003982 data->groups[num_attr_groups++] = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003983
Guenter Roeckf73cf632013-03-18 09:22:50 -07003984 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3985 fls(data->has_fan));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003986 if (IS_ERR(group))
3987 return PTR_ERR(group);
3988
Axel Lin55bdee62014-07-24 08:59:34 +08003989 data->groups[num_attr_groups++] = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003990
Guenter Roeckf73cf632013-03-18 09:22:50 -07003991 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3992 fls(data->have_temp));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003993 if (IS_ERR(group))
3994 return PTR_ERR(group);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003995
Axel Lin55bdee62014-07-24 08:59:34 +08003996 data->groups[num_attr_groups++] = group;
3997 data->groups[num_attr_groups++] = &nct6775_group_other;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003998
Guenter Roecka150d952013-07-11 22:55:22 -07003999 hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
4000 data, data->groups);
Fengguang Wu9c09bd82013-09-17 06:43:42 -07004001 return PTR_ERR_OR_ZERO(hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004002}
4003
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004004static void nct6791_enable_io_mapping(int sioaddr)
4005{
4006 int val;
4007
4008 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4009 if (val & 0x10) {
4010 pr_info("Enabling hardware monitor logical device mappings.\n");
4011 superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4012 val & ~0x10);
4013 }
4014}
4015
Guenter Roeck48e93182015-02-07 08:48:49 -08004016static int __maybe_unused nct6775_suspend(struct device *dev)
Guenter Roeck84d19d92012-12-04 08:01:39 -08004017{
4018 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08004019
4020 mutex_lock(&data->update_lock);
4021 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07004022 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004023 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
4024 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
4025 }
4026 mutex_unlock(&data->update_lock);
4027
4028 return 0;
4029}
4030
Guenter Roeck48e93182015-02-07 08:48:49 -08004031static int __maybe_unused nct6775_resume(struct device *dev)
Guenter Roeck84d19d92012-12-04 08:01:39 -08004032{
4033 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08004034 int sioreg = data->sioreg;
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004035 int i, j, err = 0;
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08004036 u8 reg;
Guenter Roeck84d19d92012-12-04 08:01:39 -08004037
4038 mutex_lock(&data->update_lock);
4039 data->bank = 0xff; /* Force initial bank selection */
4040
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08004041 err = superio_enter(sioreg);
4042 if (err)
4043 goto abort;
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004044
Guenter Roeckd2a14ea2015-02-06 18:53:21 -08004045 superio_select(sioreg, NCT6775_LD_HWM);
4046 reg = superio_inb(sioreg, SIO_REG_ENABLE);
4047 if (reg != data->sio_reg_enable)
4048 superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
4049
4050 if (data->kind == nct6791 || data->kind == nct6792)
4051 nct6791_enable_io_mapping(sioreg);
4052
4053 superio_exit(sioreg);
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004054
Guenter Roeck84d19d92012-12-04 08:01:39 -08004055 /* Restore limits */
4056 for (i = 0; i < data->in_num; i++) {
4057 if (!(data->have_in & (1 << i)))
4058 continue;
4059
4060 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
4061 data->in[i][1]);
4062 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
4063 data->in[i][2]);
4064 }
4065
Guenter Roeckc409fd42013-04-09 05:04:00 -07004066 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004067 if (!(data->has_fan_min & (1 << i)))
4068 continue;
4069
4070 nct6775_write_value(data, data->REG_FAN_MIN[i],
4071 data->fan_min[i]);
4072 }
4073
4074 for (i = 0; i < NUM_TEMP; i++) {
4075 if (!(data->have_temp & (1 << i)))
4076 continue;
4077
Guenter Roeckc409fd42013-04-09 05:04:00 -07004078 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08004079 if (data->reg_temp[j][i])
4080 nct6775_write_temp(data, data->reg_temp[j][i],
4081 data->temp[j][i]);
4082 }
4083
4084 /* Restore other settings */
4085 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07004086 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004087 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
4088 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
4089 }
4090
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004091abort:
Guenter Roeck84d19d92012-12-04 08:01:39 -08004092 /* Force re-reading all values */
4093 data->valid = false;
4094 mutex_unlock(&data->update_lock);
4095
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004096 return err;
Guenter Roeck84d19d92012-12-04 08:01:39 -08004097}
4098
Guenter Roeck48e93182015-02-07 08:48:49 -08004099static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);
Guenter Roeck84d19d92012-12-04 08:01:39 -08004100
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004101static struct platform_driver nct6775_driver = {
4102 .driver = {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004103 .name = DRVNAME,
Guenter Roeck48e93182015-02-07 08:48:49 -08004104 .pm = &nct6775_dev_pm_ops,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004105 },
4106 .probe = nct6775_probe,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004107};
4108
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004109static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004110 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004111 "NCT6775F",
4112 "NCT6776D/F",
4113 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004114 "NCT6791D",
Guenter Roeck8aefb932014-11-16 09:50:04 -08004115 "NCT6792D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004116};
4117
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004118/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004119static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004120{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004121 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004122 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004123 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004124
4125 err = superio_enter(sioaddr);
4126 if (err)
4127 return err;
4128
4129 if (force_id)
4130 val = force_id;
4131 else
4132 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4133 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4134 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004135 case SIO_NCT6106_ID:
4136 sio_data->kind = nct6106;
4137 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004138 case SIO_NCT6775_ID:
4139 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004140 break;
4141 case SIO_NCT6776_ID:
4142 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004143 break;
4144 case SIO_NCT6779_ID:
4145 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004146 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004147 case SIO_NCT6791_ID:
4148 sio_data->kind = nct6791;
4149 break;
Guenter Roeck8aefb932014-11-16 09:50:04 -08004150 case SIO_NCT6792_ID:
4151 sio_data->kind = nct6792;
4152 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004153 default:
4154 if (val != 0xffff)
4155 pr_debug("unsupported chip ID: 0x%04x\n", val);
4156 superio_exit(sioaddr);
4157 return -ENODEV;
4158 }
4159
4160 /* We have a known chip, find the HWM I/O address */
4161 superio_select(sioaddr, NCT6775_LD_HWM);
4162 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4163 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004164 addr = val & IOREGION_ALIGNMENT;
4165 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004166 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4167 superio_exit(sioaddr);
4168 return -ENODEV;
4169 }
4170
4171 /* Activate logical device if needed */
4172 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4173 if (!(val & 0x01)) {
4174 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4175 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4176 }
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004177
Guenter Roeck8aefb932014-11-16 09:50:04 -08004178 if (sio_data->kind == nct6791 || sio_data->kind == nct6792)
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004179 nct6791_enable_io_mapping(sioaddr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004180
4181 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004182 pr_info("Found %s or compatible chip at %#x:%#x\n",
4183 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004184 sio_data->sioreg = sioaddr;
4185
Guenter Roeck698a7c22013-04-05 07:35:25 -07004186 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004187}
4188
4189/*
4190 * when Super-I/O functions move to a separate file, the Super-I/O
4191 * bus will manage the lifetime of the device and this module will only keep
Guenter Roeck615fc8c2013-07-06 09:43:30 -07004192 * track of the nct6775 driver. But since we use platform_device_alloc(), we
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004193 * must keep track of the device
4194 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004195static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004196
4197static int __init sensors_nct6775_init(void)
4198{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004199 int i, err;
4200 bool found = false;
4201 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004202 struct resource res;
4203 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004204 int sioaddr[2] = { 0x2e, 0x4e };
4205
4206 err = platform_driver_register(&nct6775_driver);
4207 if (err)
4208 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004209
4210 /*
4211 * initialize sio_data->kind and sio_data->sioreg.
4212 *
4213 * when Super-I/O functions move to a separate file, the Super-I/O
4214 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4215 * nct6775 hardware monitor, and call probe()
4216 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004217 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4218 address = nct6775_find(sioaddr[i], &sio_data);
4219 if (address <= 0)
4220 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004221
Guenter Roeck698a7c22013-04-05 07:35:25 -07004222 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004223
Guenter Roeck698a7c22013-04-05 07:35:25 -07004224 pdev[i] = platform_device_alloc(DRVNAME, address);
4225 if (!pdev[i]) {
4226 err = -ENOMEM;
Axel Lin9d311ed2014-05-24 23:21:23 +08004227 goto exit_device_unregister;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004228 }
4229
4230 err = platform_device_add_data(pdev[i], &sio_data,
4231 sizeof(struct nct6775_sio_data));
4232 if (err)
4233 goto exit_device_put;
4234
4235 memset(&res, 0, sizeof(res));
4236 res.name = DRVNAME;
4237 res.start = address + IOREGION_OFFSET;
4238 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4239 res.flags = IORESOURCE_IO;
4240
4241 err = acpi_check_resource_conflict(&res);
4242 if (err) {
4243 platform_device_put(pdev[i]);
4244 pdev[i] = NULL;
4245 continue;
4246 }
4247
4248 err = platform_device_add_resources(pdev[i], &res, 1);
4249 if (err)
4250 goto exit_device_put;
4251
4252 /* platform_device_add calls probe() */
4253 err = platform_device_add(pdev[i]);
4254 if (err)
4255 goto exit_device_put;
4256 }
4257 if (!found) {
4258 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004259 goto exit_unregister;
4260 }
4261
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004262 return 0;
4263
4264exit_device_put:
Axel Lin9d311ed2014-05-24 23:21:23 +08004265 platform_device_put(pdev[i]);
4266exit_device_unregister:
4267 while (--i >= 0) {
Guenter Roeck698a7c22013-04-05 07:35:25 -07004268 if (pdev[i])
Axel Lin9d311ed2014-05-24 23:21:23 +08004269 platform_device_unregister(pdev[i]);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004270 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004271exit_unregister:
4272 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004273 return err;
4274}
4275
4276static void __exit sensors_nct6775_exit(void)
4277{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004278 int i;
4279
4280 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4281 if (pdev[i])
4282 platform_device_unregister(pdev[i]);
4283 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004284 platform_driver_unregister(&nct6775_driver);
4285}
4286
4287MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
Guenter Roeck8aefb932014-11-16 09:50:04 -08004288MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver");
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004289MODULE_LICENSE("GPL");
4290
4291module_init(sensors_nct6775_init);
4292module_exit(sensors_nct6775_exit);