blob: c0dd307001c97ce1e0a0e8e62ce1ee946970b623 [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>
60#include <linux/io.h>
61#include "lm75.h"
62
Guenter Roeckaa136e52012-12-04 03:26:05 -080063#define USE_ALTERNATE
64
Guenter Roeck8aefb932014-11-16 09:50:04 -080065enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070066
67/* used to set data->name = nct6775_device_names[data->sio_kind] */
68static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070069 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070070 "nct6775",
71 "nct6776",
72 "nct6779",
David Bartley578ab5f2013-06-24 22:28:28 -070073 "nct6791",
Guenter Roeck8aefb932014-11-16 09:50:04 -080074 "nct6792",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070075};
76
77static unsigned short force_id;
78module_param(force_id, ushort, 0);
79MODULE_PARM_DESC(force_id, "Override the detected device ID");
80
Guenter Roeck47ece962012-12-04 07:59:32 -080081static unsigned short fan_debounce;
82module_param(fan_debounce, ushort, 0);
83MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
84
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070085#define DRVNAME "nct6775"
86
87/*
88 * Super-I/O constants and functions
89 */
90
Guenter Roecka6bd5872012-12-04 03:13:34 -080091#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070092#define NCT6775_LD_HWM 0x0b
93#define NCT6775_LD_VID 0x0d
94
95#define SIO_REG_LDSEL 0x07 /* Logical device select */
96#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
97#define SIO_REG_ENABLE 0x30 /* Logical device enable */
98#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
99
Guenter Roeck6c009502012-07-01 08:23:15 -0700100#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700101#define SIO_NCT6775_ID 0xb470
102#define SIO_NCT6776_ID 0xc330
103#define SIO_NCT6779_ID 0xc560
David Bartley578ab5f2013-06-24 22:28:28 -0700104#define SIO_NCT6791_ID 0xc800
Guenter Roeck8aefb932014-11-16 09:50:04 -0800105#define SIO_NCT6792_ID 0xc910
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700106#define SIO_ID_MASK 0xFFF0
107
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800108enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
109
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700110static inline void
111superio_outb(int ioreg, int reg, int val)
112{
113 outb(reg, ioreg);
114 outb(val, ioreg + 1);
115}
116
117static inline int
118superio_inb(int ioreg, int reg)
119{
120 outb(reg, ioreg);
121 return inb(ioreg + 1);
122}
123
124static inline void
125superio_select(int ioreg, int ld)
126{
127 outb(SIO_REG_LDSEL, ioreg);
128 outb(ld, ioreg + 1);
129}
130
131static inline int
132superio_enter(int ioreg)
133{
134 /*
135 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
136 */
137 if (!request_muxed_region(ioreg, 2, DRVNAME))
138 return -EBUSY;
139
140 outb(0x87, ioreg);
141 outb(0x87, ioreg);
142
143 return 0;
144}
145
146static inline void
147superio_exit(int ioreg)
148{
149 outb(0xaa, ioreg);
150 outb(0x02, ioreg);
151 outb(0x02, ioreg + 1);
152 release_region(ioreg, 2);
153}
154
155/*
156 * ISA constants
157 */
158
159#define IOREGION_ALIGNMENT (~7)
160#define IOREGION_OFFSET 5
161#define IOREGION_LENGTH 2
162#define ADDR_REG_OFFSET 0
163#define DATA_REG_OFFSET 1
164
165#define NCT6775_REG_BANK 0x4E
166#define NCT6775_REG_CONFIG 0x40
167
168/*
169 * Not currently used:
170 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
171 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
172 * REG_MAN_ID is at port 0x4f
173 * REG_CHIP_ID is at port 0x58
174 */
175
Guenter Roeckaa136e52012-12-04 03:26:05 -0800176#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
177#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
178
Guenter Roeck6c009502012-07-01 08:23:15 -0700179#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck30846992013-06-24 22:21:59 -0700180#define NUM_REG_BEEP 5 /* Max number of beep registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700181
David Bartley578ab5f2013-06-24 22:28:28 -0700182#define NUM_FAN 6
183
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700184/* Common and NCT6775 specific data */
185
186/* Voltage min/max registers for nr=7..14 are in bank 5 */
187
188static const u16 NCT6775_REG_IN_MAX[] = {
189 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
190 0x55c, 0x55e, 0x560, 0x562 };
191static const u16 NCT6775_REG_IN_MIN[] = {
192 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
193 0x55d, 0x55f, 0x561, 0x563 };
194static const u16 NCT6775_REG_IN[] = {
195 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
196};
197
198#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800199#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700200#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700201
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800202#define NCT6775_REG_FANDIV1 0x506
203#define NCT6775_REG_FANDIV2 0x507
204
Guenter Roeck47ece962012-12-04 07:59:32 -0800205#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
206
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700207static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
208
Guenter Roeck30846992013-06-24 22:21:59 -0700209/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700210
211static const s8 NCT6775_ALARM_BITS[] = {
212 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
213 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
214 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700215 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700216 -1, -1, -1, /* unused */
217 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
218 12, -1 }; /* intrusion0, intrusion1 */
219
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800220#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800221#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800222#define INTRUSION_ALARM_BASE 30
223
Guenter Roeck30846992013-06-24 22:21:59 -0700224static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
225
226/*
227 * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
228 * 30..31 intrusion
229 */
230static const s8 NCT6775_BEEP_BITS[] = {
231 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
232 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
233 21, /* global beep enable */
234 6, 7, 11, 28, -1, /* fan1..fan5 */
235 -1, -1, -1, /* unused */
236 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
237 12, -1 }; /* intrusion0, intrusion1 */
238
239#define BEEP_ENABLE_BASE 15
240
Guenter Roecka6bd5872012-12-04 03:13:34 -0800241static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
242static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
243
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800244/* DC or PWM output fan configuration */
245static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
246static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
247
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800248/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800249
David Bartley578ab5f2013-06-24 22:28:28 -0700250static const u16 NCT6775_REG_TARGET[] = {
251 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
252static const u16 NCT6775_REG_FAN_MODE[] = {
253 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800254static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700255 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800256static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700257 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800258static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700259 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
260static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
261 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800262static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
263static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
264
265static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700266 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
267static const u16 NCT6775_REG_PWM[] = {
268 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
269static const u16 NCT6775_REG_PWM_READ[] = {
270 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800271
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800272static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
273static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800274static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
David Bartley578ab5f2013-06-24 22:28:28 -0700275static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800276
Guenter Roeckaa136e52012-12-04 03:26:05 -0800277static const u16 NCT6775_REG_TEMP[] = {
278 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
279
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800280static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
281
Guenter Roeckaa136e52012-12-04 03:26:05 -0800282static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
283 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
284static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
285 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
286static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
287 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
288
289static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
290 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
291
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800292static const u16 NCT6775_REG_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700293 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800294
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800295static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700296 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800297static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700298 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800299static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700300 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800301static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700302 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800303static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700304 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800305
Guenter Roeckaa136e52012-12-04 03:26:05 -0800306static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
307
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800308static const u16 NCT6775_REG_AUTO_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700309 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800310static const u16 NCT6775_REG_AUTO_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700311 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800312
313#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
314#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
315
316static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
317
318static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700319 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800320static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700321 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800322
Guenter Roeckaa136e52012-12-04 03:26:05 -0800323static const char *const nct6775_temp_label[] = {
324 "",
325 "SYSTIN",
326 "CPUTIN",
327 "AUXTIN",
328 "AMD SB-TSI",
329 "PECI Agent 0",
330 "PECI Agent 1",
331 "PECI Agent 2",
332 "PECI Agent 3",
333 "PECI Agent 4",
334 "PECI Agent 5",
335 "PECI Agent 6",
336 "PECI Agent 7",
337 "PCH_CHIP_CPU_MAX_TEMP",
338 "PCH_CHIP_TEMP",
339 "PCH_CPU_TEMP",
340 "PCH_MCH_TEMP",
341 "PCH_DIM0_TEMP",
342 "PCH_DIM1_TEMP",
343 "PCH_DIM2_TEMP",
344 "PCH_DIM3_TEMP"
345};
346
347static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
348 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
349
350static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
351 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
352 0xa07 };
353
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700354/* NCT6776 specific data */
355
356static const s8 NCT6776_ALARM_BITS[] = {
357 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
358 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
359 -1, /* unused */
360 6, 7, 11, 10, 23, /* fan1..fan5 */
361 -1, -1, -1, /* unused */
362 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
363 12, 9 }; /* intrusion0, intrusion1 */
364
Guenter Roeck30846992013-06-24 22:21:59 -0700365static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
366
367static const s8 NCT6776_BEEP_BITS[] = {
368 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
369 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
370 24, /* global beep enable */
371 25, 26, 27, 28, 29, /* fan1..fan5 */
372 -1, -1, -1, /* unused */
373 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
374 30, 31 }; /* intrusion0, intrusion1 */
375
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800376static const u16 NCT6776_REG_TOLERANCE_H[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700377 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800378
David Bartley578ab5f2013-06-24 22:28:28 -0700379static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
380static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800381
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800382static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800383static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800384
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800385static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700386 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800387
Guenter Roeckaa136e52012-12-04 03:26:05 -0800388static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
389 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
390
391static const char *const nct6776_temp_label[] = {
392 "",
393 "SYSTIN",
394 "CPUTIN",
395 "AUXTIN",
396 "SMBUSMASTER 0",
397 "SMBUSMASTER 1",
398 "SMBUSMASTER 2",
399 "SMBUSMASTER 3",
400 "SMBUSMASTER 4",
401 "SMBUSMASTER 5",
402 "SMBUSMASTER 6",
403 "SMBUSMASTER 7",
404 "PECI Agent 0",
405 "PECI Agent 1",
406 "PCH_CHIP_CPU_MAX_TEMP",
407 "PCH_CHIP_TEMP",
408 "PCH_CPU_TEMP",
409 "PCH_MCH_TEMP",
410 "PCH_DIM0_TEMP",
411 "PCH_DIM1_TEMP",
412 "PCH_DIM2_TEMP",
413 "PCH_DIM3_TEMP",
414 "BYTE_TEMP"
415};
416
417static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
418 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
419
420static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
421 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
422
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700423/* NCT6779 specific data */
424
425static const u16 NCT6779_REG_IN[] = {
426 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
427 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
428
429static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
430 0x459, 0x45A, 0x45B, 0x568 };
431
432static const s8 NCT6779_ALARM_BITS[] = {
433 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
434 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
435 -1, /* unused */
436 6, 7, 11, 10, 23, /* fan1..fan5 */
437 -1, -1, -1, /* unused */
438 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
439 12, 9 }; /* intrusion0, intrusion1 */
440
Guenter Roeck30846992013-06-24 22:21:59 -0700441static const s8 NCT6779_BEEP_BITS[] = {
442 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
443 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
444 24, /* global beep enable */
445 25, 26, 27, 28, 29, /* fan1..fan5 */
446 -1, -1, -1, /* unused */
447 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
448 30, 31 }; /* intrusion0, intrusion1 */
449
David Bartley578ab5f2013-06-24 22:28:28 -0700450static const u16 NCT6779_REG_FAN[] = {
451 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800452static const u16 NCT6779_REG_FAN_PULSES[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700453 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800454
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800455static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700456 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700457#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800458static const u16 NCT6779_REG_CRITICAL_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700459 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800460
Guenter Roeckaa136e52012-12-04 03:26:05 -0800461static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800462static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
Guenter Roeckaa136e52012-12-04 03:26:05 -0800463static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
464 0x18, 0x152 };
465static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
466 0x3a, 0x153 };
467static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
468 0x39, 0x155 };
469
470static const u16 NCT6779_REG_TEMP_OFFSET[] = {
471 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
472
473static const char *const nct6779_temp_label[] = {
474 "",
475 "SYSTIN",
476 "CPUTIN",
477 "AUXTIN0",
478 "AUXTIN1",
479 "AUXTIN2",
480 "AUXTIN3",
481 "",
482 "SMBUSMASTER 0",
483 "SMBUSMASTER 1",
484 "SMBUSMASTER 2",
485 "SMBUSMASTER 3",
486 "SMBUSMASTER 4",
487 "SMBUSMASTER 5",
488 "SMBUSMASTER 6",
489 "SMBUSMASTER 7",
490 "PECI Agent 0",
491 "PECI Agent 1",
492 "PCH_CHIP_CPU_MAX_TEMP",
493 "PCH_CHIP_TEMP",
494 "PCH_CPU_TEMP",
495 "PCH_MCH_TEMP",
496 "PCH_DIM0_TEMP",
497 "PCH_DIM1_TEMP",
498 "PCH_DIM2_TEMP",
499 "PCH_DIM3_TEMP",
500 "BYTE_TEMP"
501};
502
503static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
504 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
505 0, 0, 0, 0, 0, 0, 0, 0,
506 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
507 0x408, 0 };
508
509static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
510 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
511
David Bartley578ab5f2013-06-24 22:28:28 -0700512/* NCT6791 specific data */
513
514#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
515
Guenter Roeckcc76dee2013-11-13 12:47:17 -0800516static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[6] = { 0, 0x239 };
517static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[6] = { 0, 0x23a };
518static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[6] = { 0, 0x23b };
519static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[6] = { 0, 0x23c };
520static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[6] = { 0, 0x23d };
521static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[6] = { 0, 0x23e };
522
David Bartley578ab5f2013-06-24 22:28:28 -0700523static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
524 0x459, 0x45A, 0x45B, 0x568, 0x45D };
525
526static const s8 NCT6791_ALARM_BITS[] = {
527 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
528 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
529 -1, /* unused */
530 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
531 -1, -1, /* unused */
532 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
533 12, 9 }; /* intrusion0, intrusion1 */
534
Guenter Roeck8aefb932014-11-16 09:50:04 -0800535/* NCT6792 specific data */
536
537static const u16 NCT6792_REG_TEMP_MON[] = {
538 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
539static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
540 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
David Bartley578ab5f2013-06-24 22:28:28 -0700541
Guenter Roeck6c009502012-07-01 08:23:15 -0700542/* NCT6102D/NCT6106D specific data */
543
544#define NCT6106_REG_VBAT 0x318
545#define NCT6106_REG_DIODE 0x319
546#define NCT6106_DIODE_MASK 0x01
547
548static const u16 NCT6106_REG_IN_MAX[] = {
549 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
550static const u16 NCT6106_REG_IN_MIN[] = {
551 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
552static const u16 NCT6106_REG_IN[] = {
553 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
554
555static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800556static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
Guenter Roeck6c009502012-07-01 08:23:15 -0700557static const u16 NCT6106_REG_TEMP_HYST[] = {
558 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
559static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700560 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
561static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
562 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
563static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
564 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700565static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
566static const u16 NCT6106_REG_TEMP_CONFIG[] = {
567 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
568
569static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
570static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
571static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
572static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
573
574static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
575static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
576static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
577static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
578static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
579static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
580static const u16 NCT6106_REG_TEMP_SOURCE[] = {
581 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
582
583static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
584static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
585 0x11b, 0x12b, 0x13b };
586
587static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
588#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
589static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
590
591static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
592static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
593static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
594static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
595static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
596static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
597
598static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
599
600static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
601static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
602static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
603static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
604static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
605static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
606
607static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
608static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
609
610static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
611 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
612
613static const s8 NCT6106_ALARM_BITS[] = {
614 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
615 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
616 -1, /* unused */
617 32, 33, 34, -1, -1, /* fan1..fan5 */
618 -1, -1, -1, /* unused */
619 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
620 48, -1 /* intrusion0, intrusion1 */
621};
622
Guenter Roeck30846992013-06-24 22:21:59 -0700623static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
624 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
625
626static const s8 NCT6106_BEEP_BITS[] = {
627 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
628 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
629 32, /* global beep enable */
630 24, 25, 26, 27, 28, /* fan1..fan5 */
631 -1, -1, -1, /* unused */
632 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
633 34, -1 /* intrusion0, intrusion1 */
634};
635
Guenter Roeck6c009502012-07-01 08:23:15 -0700636static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
637 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
638
639static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
640 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
641
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800642static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
643{
644 if (mode == 0 && pwm == 255)
645 return off;
646 return mode + 1;
647}
648
649static int pwm_enable_to_reg(enum pwm_enable mode)
650{
651 if (mode == off)
652 return 0;
653 return mode - 1;
654}
655
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700656/*
657 * Conversions
658 */
659
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800660/* 1 is DC mode, output in ms */
661static unsigned int step_time_from_reg(u8 reg, u8 mode)
662{
663 return mode ? 400 * reg : 100 * reg;
664}
665
666static u8 step_time_to_reg(unsigned int msec, u8 mode)
667{
668 return clamp_val((mode ? (msec + 200) / 400 :
669 (msec + 50) / 100), 1, 255);
670}
671
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800672static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
673{
674 if (reg == 0 || reg == 255)
675 return 0;
676 return 1350000U / (reg << divreg);
677}
678
679static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
680{
681 if ((reg & 0xff1f) == 0xff1f)
682 return 0;
683
684 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
685
686 if (reg == 0)
687 return 0;
688
689 return 1350000U / reg;
690}
691
692static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
693{
694 if (reg == 0 || reg == 0xffff)
695 return 0;
696
697 /*
698 * Even though the registers are 16 bit wide, the fan divisor
699 * still applies.
700 */
701 return 1350000U / (reg << divreg);
702}
703
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800704static u16 fan_to_reg(u32 fan, unsigned int divreg)
705{
706 if (!fan)
707 return 0;
708
709 return (1350000U / fan) >> divreg;
710}
711
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800712static inline unsigned int
713div_from_reg(u8 reg)
714{
715 return 1 << reg;
716}
717
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700718/*
719 * Some of the voltage inputs have internal scaling, the tables below
720 * contain 8 (the ADC LSB in mV) * scaling factor * 100
721 */
722static const u16 scale_in[15] = {
723 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
724 800, 800
725};
726
727static inline long in_from_reg(u8 reg, u8 nr)
728{
729 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
730}
731
732static inline u8 in_to_reg(u32 val, u8 nr)
733{
734 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
735}
736
737/*
738 * Data structures and manipulation thereof
739 */
740
741struct nct6775_data {
742 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700743 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700744 enum kinds kind;
745 const char *name;
746
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700747 const struct attribute_group *groups[6];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700748
Guenter Roeckb7a61352013-04-02 22:14:06 -0700749 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
750 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800751 */
752 u8 temp_src[NUM_TEMP];
753 u16 reg_temp_config[NUM_TEMP];
754 const char * const *temp_label;
755 int temp_label_num;
756
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700757 u16 REG_CONFIG;
758 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800759 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700760 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700761
762 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700763 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700764
765 const u16 *REG_VIN;
766 const u16 *REG_IN_MINMAX[2];
767
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800768 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800769 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800770 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800771 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800772 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700773 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800774 const u16 *REG_FAN_TIME[3];
775
776 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800777
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800778 const u8 *REG_PWM_MODE;
779 const u8 *PWM_MODE_MASK;
780
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800781 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
782 * [3]=pwm_max, [4]=pwm_step,
783 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800784 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800785 const u16 *REG_PWM_READ;
786
Guenter Roeck6c009502012-07-01 08:23:15 -0700787 const u16 *REG_CRITICAL_PWM_ENABLE;
788 u8 CRITICAL_PWM_ENABLE_MASK;
789 const u16 *REG_CRITICAL_PWM;
790
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800791 const u16 *REG_AUTO_TEMP;
792 const u16 *REG_AUTO_PWM;
793
794 const u16 *REG_CRITICAL_TEMP;
795 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
796
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800797 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800798 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800799 const u16 *REG_WEIGHT_TEMP_SEL;
800 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
801
Guenter Roeckaa136e52012-12-04 03:26:05 -0800802 const u16 *REG_TEMP_OFFSET;
803
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700804 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700805 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700806
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800807 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
808 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
809
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700810 struct mutex update_lock;
811 bool valid; /* true if following fields are valid */
812 unsigned long last_updated; /* In jiffies */
813
814 /* Register values */
815 u8 bank; /* current register bank */
816 u8 in_num; /* number of in inputs we have */
817 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700818 unsigned int rpm[NUM_FAN];
819 u16 fan_min[NUM_FAN];
820 u8 fan_pulses[NUM_FAN];
821 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800822 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800823 u8 has_fan; /* some fan inputs can be disabled */
824 u8 has_fan_min; /* some fans don't have min register */
825 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700826
Guenter Roeck6c009502012-07-01 08:23:15 -0700827 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700828 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800829 u8 temp_fixed_num; /* 3 or 6 */
830 u8 temp_type[NUM_TEMP_FIXED];
831 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300832 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
833 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700834 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700835 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700836
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800837 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700838 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
839 * 0->PWM variable duty cycle
840 */
841 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800842 /* 0->off
843 * 1->manual
844 * 2->thermal cruise mode (also called SmartFan I)
845 * 3->fan speed cruise mode
846 * 4->SmartFan III
847 * 5->enhanced variable thermal cruise (SmartFan IV)
848 */
David Bartley578ab5f2013-06-24 22:28:28 -0700849 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
850 * [3]=pwm_max, [4]=pwm_step,
851 * [5]=weight_duty_step, [6]=weight_duty_base
852 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800853
David Bartley578ab5f2013-06-24 22:28:28 -0700854 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800855 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700856 u32 target_speed[NUM_FAN];
857 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800858 u8 speed_tolerance_limit;
859
David Bartley578ab5f2013-06-24 22:28:28 -0700860 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800861 u8 tolerance_mask;
862
David Bartley578ab5f2013-06-24 22:28:28 -0700863 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800864
865 /* Automatic fan speed control registers */
866 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700867 u8 auto_pwm[NUM_FAN][7];
868 u8 auto_temp[NUM_FAN][7];
869 u8 pwm_temp_sel[NUM_FAN];
870 u8 pwm_weight_temp_sel[NUM_FAN];
871 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
872 * 2->temp_base
873 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800874
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700875 u8 vid;
876 u8 vrm;
877
Guenter Roeckf73cf632013-03-18 09:22:50 -0700878 bool have_vid;
879
Guenter Roeckaa136e52012-12-04 03:26:05 -0800880 u16 have_temp;
881 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700882 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800883#ifdef CONFIG_PM
884 /* Remember extra register values over suspend/resume */
885 u8 vbat;
886 u8 fandiv1;
887 u8 fandiv2;
888#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700889};
890
891struct nct6775_sio_data {
892 int sioreg;
893 enum kinds kind;
894};
895
Guenter Roeckf73cf632013-03-18 09:22:50 -0700896struct sensor_device_template {
897 struct device_attribute dev_attr;
898 union {
899 struct {
900 u8 nr;
901 u8 index;
902 } s;
903 int index;
904 } u;
905 bool s2; /* true if both index and nr are used */
906};
907
908struct sensor_device_attr_u {
909 union {
910 struct sensor_device_attribute a1;
911 struct sensor_device_attribute_2 a2;
912 } u;
913 char name[32];
914};
915
916#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
917 .attr = {.name = _template, .mode = _mode }, \
918 .show = _show, \
919 .store = _store, \
920}
921
922#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
923 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
924 .u.index = _index, \
925 .s2 = false }
926
927#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
928 _nr, _index) \
929 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
930 .u.s.index = _index, \
931 .u.s.nr = _nr, \
932 .s2 = true }
933
934#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
935static struct sensor_device_template sensor_dev_template_##_name \
936 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
937 _index)
938
939#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
940 _nr, _index) \
941static struct sensor_device_template sensor_dev_template_##_name \
942 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
943 _nr, _index)
944
945struct sensor_template_group {
946 struct sensor_device_template **templates;
947 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
948 int base;
949};
950
951static struct attribute_group *
952nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
953 int repeat)
954{
955 struct attribute_group *group;
956 struct sensor_device_attr_u *su;
957 struct sensor_device_attribute *a;
958 struct sensor_device_attribute_2 *a2;
959 struct attribute **attrs;
960 struct sensor_device_template **t;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300961 int i, count;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700962
963 if (repeat <= 0)
964 return ERR_PTR(-EINVAL);
965
966 t = tg->templates;
967 for (count = 0; *t; t++, count++)
968 ;
969
970 if (count == 0)
971 return ERR_PTR(-EINVAL);
972
973 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
974 if (group == NULL)
975 return ERR_PTR(-ENOMEM);
976
977 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
978 GFP_KERNEL);
979 if (attrs == NULL)
980 return ERR_PTR(-ENOMEM);
981
982 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
983 GFP_KERNEL);
984 if (su == NULL)
985 return ERR_PTR(-ENOMEM);
986
987 group->attrs = attrs;
988 group->is_visible = tg->is_visible;
989
990 for (i = 0; i < repeat; i++) {
991 t = tg->templates;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300992 while (*t != NULL) {
Guenter Roeckf73cf632013-03-18 09:22:50 -0700993 snprintf(su->name, sizeof(su->name),
994 (*t)->dev_attr.attr.name, tg->base + i);
995 if ((*t)->s2) {
996 a2 = &su->u.a2;
997 a2->dev_attr.attr.name = su->name;
998 a2->nr = (*t)->u.s.nr + i;
999 a2->index = (*t)->u.s.index;
1000 a2->dev_attr.attr.mode =
1001 (*t)->dev_attr.attr.mode;
1002 a2->dev_attr.show = (*t)->dev_attr.show;
1003 a2->dev_attr.store = (*t)->dev_attr.store;
1004 *attrs = &a2->dev_attr.attr;
1005 } else {
1006 a = &su->u.a1;
1007 a->dev_attr.attr.name = su->name;
1008 a->index = (*t)->u.index + i;
1009 a->dev_attr.attr.mode =
1010 (*t)->dev_attr.attr.mode;
1011 a->dev_attr.show = (*t)->dev_attr.show;
1012 a->dev_attr.store = (*t)->dev_attr.store;
1013 *attrs = &a->dev_attr.attr;
1014 }
1015 attrs++;
1016 su++;
1017 t++;
1018 }
1019 }
1020
Guenter Roeckf73cf632013-03-18 09:22:50 -07001021 return group;
1022}
1023
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001024static bool is_word_sized(struct nct6775_data *data, u16 reg)
1025{
1026 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001027 case nct6106:
1028 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1029 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1030 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001031 case nct6775:
1032 return (((reg & 0xff00) == 0x100 ||
1033 (reg & 0xff00) == 0x200) &&
1034 ((reg & 0x00ff) == 0x50 ||
1035 (reg & 0x00ff) == 0x53 ||
1036 (reg & 0x00ff) == 0x55)) ||
1037 (reg & 0xfff0) == 0x630 ||
1038 reg == 0x640 || reg == 0x642 ||
1039 reg == 0x662 ||
1040 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1041 reg == 0x73 || reg == 0x75 || reg == 0x77;
1042 case nct6776:
1043 return (((reg & 0xff00) == 0x100 ||
1044 (reg & 0xff00) == 0x200) &&
1045 ((reg & 0x00ff) == 0x50 ||
1046 (reg & 0x00ff) == 0x53 ||
1047 (reg & 0x00ff) == 0x55)) ||
1048 (reg & 0xfff0) == 0x630 ||
1049 reg == 0x402 ||
1050 reg == 0x640 || reg == 0x642 ||
1051 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1052 reg == 0x73 || reg == 0x75 || reg == 0x77;
1053 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001054 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08001055 case nct6792:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001056 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001057 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001058 reg == 0x402 ||
1059 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1060 reg == 0x640 || reg == 0x642 ||
1061 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
Guenter Roeck8aefb932014-11-16 09:50:04 -08001062 reg == 0x7b || reg == 0x7d;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001063 }
1064 return false;
1065}
1066
1067/*
1068 * On older chips, only registers 0x50-0x5f are banked.
1069 * On more recent chips, all registers are banked.
1070 * Assume that is the case and set the bank number for each access.
1071 * Cache the bank number so it only needs to be set if it changes.
1072 */
1073static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1074{
1075 u8 bank = reg >> 8;
1076 if (data->bank != bank) {
1077 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1078 outb_p(bank, data->addr + DATA_REG_OFFSET);
1079 data->bank = bank;
1080 }
1081}
1082
1083static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1084{
1085 int res, word_sized = is_word_sized(data, reg);
1086
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001087 nct6775_set_bank(data, reg);
1088 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1089 res = inb_p(data->addr + DATA_REG_OFFSET);
1090 if (word_sized) {
1091 outb_p((reg & 0xff) + 1,
1092 data->addr + ADDR_REG_OFFSET);
1093 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1094 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001095 return res;
1096}
1097
1098static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1099{
1100 int word_sized = is_word_sized(data, reg);
1101
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001102 nct6775_set_bank(data, reg);
1103 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1104 if (word_sized) {
1105 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1106 outb_p((reg & 0xff) + 1,
1107 data->addr + ADDR_REG_OFFSET);
1108 }
1109 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001110 return 0;
1111}
1112
Guenter Roeckaa136e52012-12-04 03:26:05 -08001113/* We left-align 8-bit temperature values to make the code simpler */
1114static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1115{
1116 u16 res;
1117
1118 res = nct6775_read_value(data, reg);
1119 if (!is_word_sized(data, reg))
1120 res <<= 8;
1121
1122 return res;
1123}
1124
1125static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1126{
1127 if (!is_word_sized(data, reg))
1128 value >>= 8;
1129 return nct6775_write_value(data, reg, value);
1130}
1131
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001132/* This function assumes that the caller holds data->update_lock */
1133static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1134{
1135 u8 reg;
1136
1137 switch (nr) {
1138 case 0:
1139 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1140 | (data->fan_div[0] & 0x7);
1141 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1142 break;
1143 case 1:
1144 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1145 | ((data->fan_div[1] << 4) & 0x70);
1146 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1147 break;
1148 case 2:
1149 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1150 | (data->fan_div[2] & 0x7);
1151 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1152 break;
1153 case 3:
1154 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1155 | ((data->fan_div[3] << 4) & 0x70);
1156 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1157 break;
1158 }
1159}
1160
1161static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1162{
1163 if (data->kind == nct6775)
1164 nct6775_write_fan_div(data, nr);
1165}
1166
1167static void nct6775_update_fan_div(struct nct6775_data *data)
1168{
1169 u8 i;
1170
1171 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1172 data->fan_div[0] = i & 0x7;
1173 data->fan_div[1] = (i & 0x70) >> 4;
1174 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1175 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001176 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001177 data->fan_div[3] = (i & 0x70) >> 4;
1178}
1179
1180static void nct6775_update_fan_div_common(struct nct6775_data *data)
1181{
1182 if (data->kind == nct6775)
1183 nct6775_update_fan_div(data);
1184}
1185
1186static void nct6775_init_fan_div(struct nct6775_data *data)
1187{
1188 int i;
1189
1190 nct6775_update_fan_div_common(data);
1191 /*
1192 * For all fans, start with highest divider value if the divider
1193 * register is not initialized. This ensures that we get a
1194 * reading from the fan count register, even if it is not optimal.
1195 * We'll compute a better divider later on.
1196 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001197 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001198 if (!(data->has_fan & (1 << i)))
1199 continue;
1200 if (data->fan_div[i] == 0) {
1201 data->fan_div[i] = 7;
1202 nct6775_write_fan_div_common(data, i);
1203 }
1204 }
1205}
1206
1207static void nct6775_init_fan_common(struct device *dev,
1208 struct nct6775_data *data)
1209{
1210 int i;
1211 u8 reg;
1212
1213 if (data->has_fan_div)
1214 nct6775_init_fan_div(data);
1215
1216 /*
1217 * If fan_min is not set (0), set it to 0xff to disable it. This
1218 * prevents the unnecessary warning when fanX_min is reported as 0.
1219 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001220 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001221 if (data->has_fan_min & (1 << i)) {
1222 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1223 if (!reg)
1224 nct6775_write_value(data, data->REG_FAN_MIN[i],
1225 data->has_fan_div ? 0xff
1226 : 0xff1f);
1227 }
1228 }
1229}
1230
1231static void nct6775_select_fan_div(struct device *dev,
1232 struct nct6775_data *data, int nr, u16 reg)
1233{
1234 u8 fan_div = data->fan_div[nr];
1235 u16 fan_min;
1236
1237 if (!data->has_fan_div)
1238 return;
1239
1240 /*
1241 * If we failed to measure the fan speed, or the reported value is not
1242 * in the optimal range, and the clock divider can be modified,
1243 * let's try that for next time.
1244 */
1245 if (reg == 0x00 && fan_div < 0x07)
1246 fan_div++;
1247 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1248 fan_div--;
1249
1250 if (fan_div != data->fan_div[nr]) {
1251 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1252 nr + 1, div_from_reg(data->fan_div[nr]),
1253 div_from_reg(fan_div));
1254
1255 /* Preserve min limit if possible */
1256 if (data->has_fan_min & (1 << nr)) {
1257 fan_min = data->fan_min[nr];
1258 if (fan_div > data->fan_div[nr]) {
1259 if (fan_min != 255 && fan_min > 1)
1260 fan_min >>= 1;
1261 } else {
1262 if (fan_min != 255) {
1263 fan_min <<= 1;
1264 if (fan_min > 254)
1265 fan_min = 254;
1266 }
1267 }
1268 if (fan_min != data->fan_min[nr]) {
1269 data->fan_min[nr] = fan_min;
1270 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1271 fan_min);
1272 }
1273 }
1274 data->fan_div[nr] = fan_div;
1275 nct6775_write_fan_div_common(data, nr);
1276 }
1277}
1278
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001279static void nct6775_update_pwm(struct device *dev)
1280{
1281 struct nct6775_data *data = dev_get_drvdata(dev);
1282 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001283 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001284 bool duty_is_dc;
1285
1286 for (i = 0; i < data->pwm_num; i++) {
1287 if (!(data->has_pwm & (1 << i)))
1288 continue;
1289
1290 duty_is_dc = data->REG_PWM_MODE[i] &&
1291 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1292 & data->PWM_MODE_MASK[i]);
1293 data->pwm_mode[i] = duty_is_dc;
1294
1295 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1296 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1297 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1298 data->pwm[j][i]
1299 = nct6775_read_value(data,
1300 data->REG_PWM[j][i]);
1301 }
1302 }
1303
1304 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1305 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001306
1307 if (!data->temp_tolerance[0][i] ||
1308 data->pwm_enable[i] != speed_cruise)
1309 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1310 if (!data->target_speed_tolerance[i] ||
1311 data->pwm_enable[i] == speed_cruise) {
1312 u8 t = fanmodecfg & 0x0f;
1313 if (data->REG_TOLERANCE_H) {
1314 t |= (nct6775_read_value(data,
1315 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1316 }
1317 data->target_speed_tolerance[i] = t;
1318 }
1319
1320 data->temp_tolerance[1][i] =
1321 nct6775_read_value(data,
1322 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1323
1324 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1325 data->pwm_temp_sel[i] = reg & 0x1f;
1326 /* If fan can stop, report floor as 0 */
1327 if (reg & 0x80)
1328 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001329
Guenter Roeckcc76dee2013-11-13 12:47:17 -08001330 if (!data->REG_WEIGHT_TEMP_SEL[i])
1331 continue;
1332
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001333 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1334 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1335 /* If weight is disabled, report weight source as 0 */
1336 if (j == 1 && !(reg & 0x80))
1337 data->pwm_weight_temp_sel[i] = 0;
1338
1339 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001340 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001341 data->weight_temp[j][i]
1342 = nct6775_read_value(data,
1343 data->REG_WEIGHT_TEMP[j][i]);
1344 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001345 }
1346}
1347
1348static void nct6775_update_pwm_limits(struct device *dev)
1349{
1350 struct nct6775_data *data = dev_get_drvdata(dev);
1351 int i, j;
1352 u8 reg;
1353 u16 reg_t;
1354
1355 for (i = 0; i < data->pwm_num; i++) {
1356 if (!(data->has_pwm & (1 << i)))
1357 continue;
1358
Guenter Roeckc409fd42013-04-09 05:04:00 -07001359 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001360 data->fan_time[j][i] =
1361 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1362 }
1363
1364 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1365 /* Update only in matching mode or if never updated */
1366 if (!data->target_temp[i] ||
1367 data->pwm_enable[i] == thermal_cruise)
1368 data->target_temp[i] = reg_t & data->target_temp_mask;
1369 if (!data->target_speed[i] ||
1370 data->pwm_enable[i] == speed_cruise) {
1371 if (data->REG_TOLERANCE_H) {
1372 reg_t |= (nct6775_read_value(data,
1373 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1374 }
1375 data->target_speed[i] = reg_t;
1376 }
1377
1378 for (j = 0; j < data->auto_pwm_num; j++) {
1379 data->auto_pwm[i][j] =
1380 nct6775_read_value(data,
1381 NCT6775_AUTO_PWM(data, i, j));
1382 data->auto_temp[i][j] =
1383 nct6775_read_value(data,
1384 NCT6775_AUTO_TEMP(data, i, j));
1385 }
1386
1387 /* critical auto_pwm temperature data */
1388 data->auto_temp[i][data->auto_pwm_num] =
1389 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1390
1391 switch (data->kind) {
1392 case nct6775:
1393 reg = nct6775_read_value(data,
1394 NCT6775_REG_CRITICAL_ENAB[i]);
1395 data->auto_pwm[i][data->auto_pwm_num] =
1396 (reg & 0x02) ? 0xff : 0x00;
1397 break;
1398 case nct6776:
1399 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1400 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001401 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001402 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001403 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08001404 case nct6792:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001405 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001406 data->REG_CRITICAL_PWM_ENABLE[i]);
1407 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1408 reg = nct6775_read_value(data,
1409 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001410 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001411 reg = 0xff;
1412 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001413 break;
1414 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001415 }
1416}
1417
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001418static struct nct6775_data *nct6775_update_device(struct device *dev)
1419{
1420 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001421 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001422
1423 mutex_lock(&data->update_lock);
1424
Guenter Roeck6445e662013-04-21 09:13:28 -07001425 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001426 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001427 /* Fan clock dividers */
1428 nct6775_update_fan_div_common(data);
1429
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001430 /* Measured voltages and limits */
1431 for (i = 0; i < data->in_num; i++) {
1432 if (!(data->have_in & (1 << i)))
1433 continue;
1434
1435 data->in[i][0] = nct6775_read_value(data,
1436 data->REG_VIN[i]);
1437 data->in[i][1] = nct6775_read_value(data,
1438 data->REG_IN_MINMAX[0][i]);
1439 data->in[i][2] = nct6775_read_value(data,
1440 data->REG_IN_MINMAX[1][i]);
1441 }
1442
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001443 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001444 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001445 u16 reg;
1446
1447 if (!(data->has_fan & (1 << i)))
1448 continue;
1449
1450 reg = nct6775_read_value(data, data->REG_FAN[i]);
1451 data->rpm[i] = data->fan_from_reg(reg,
1452 data->fan_div[i]);
1453
1454 if (data->has_fan_min & (1 << i))
1455 data->fan_min[i] = nct6775_read_value(data,
1456 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001457 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001458 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1459 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001460
1461 nct6775_select_fan_div(dev, data, i, reg);
1462 }
1463
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001464 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001465 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001466
Guenter Roeckaa136e52012-12-04 03:26:05 -08001467 /* Measured temperatures and limits */
1468 for (i = 0; i < NUM_TEMP; i++) {
1469 if (!(data->have_temp & (1 << i)))
1470 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001471 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001472 if (data->reg_temp[j][i])
1473 data->temp[j][i]
1474 = nct6775_read_temp(data,
1475 data->reg_temp[j][i]);
1476 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001477 if (i >= NUM_TEMP_FIXED ||
1478 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001479 continue;
1480 data->temp_offset[i]
1481 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1482 }
1483
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001484 data->alarms = 0;
1485 for (i = 0; i < NUM_REG_ALARM; i++) {
1486 u8 alarm;
1487 if (!data->REG_ALARM[i])
1488 continue;
1489 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1490 data->alarms |= ((u64)alarm) << (i << 3);
1491 }
1492
Guenter Roeck30846992013-06-24 22:21:59 -07001493 data->beeps = 0;
1494 for (i = 0; i < NUM_REG_BEEP; i++) {
1495 u8 beep;
1496 if (!data->REG_BEEP[i])
1497 continue;
1498 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1499 data->beeps |= ((u64)beep) << (i << 3);
1500 }
1501
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001502 data->last_updated = jiffies;
1503 data->valid = true;
1504 }
1505
1506 mutex_unlock(&data->update_lock);
1507 return data;
1508}
1509
1510/*
1511 * Sysfs callback functions
1512 */
1513static ssize_t
1514show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1515{
1516 struct nct6775_data *data = nct6775_update_device(dev);
1517 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1518 int nr = sattr->nr;
1519 int index = sattr->index;
1520 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1521}
1522
1523static ssize_t
1524store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1525 size_t count)
1526{
1527 struct nct6775_data *data = dev_get_drvdata(dev);
1528 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1529 int nr = sattr->nr;
1530 int index = sattr->index;
1531 unsigned long val;
1532 int err = kstrtoul(buf, 10, &val);
1533 if (err < 0)
1534 return err;
1535 mutex_lock(&data->update_lock);
1536 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001537 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001538 data->in[nr][index]);
1539 mutex_unlock(&data->update_lock);
1540 return count;
1541}
1542
1543static ssize_t
1544show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1545{
1546 struct nct6775_data *data = nct6775_update_device(dev);
1547 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1548 int nr = data->ALARM_BITS[sattr->index];
1549 return sprintf(buf, "%u\n",
1550 (unsigned int)((data->alarms >> nr) & 0x01));
1551}
1552
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001553static int find_temp_source(struct nct6775_data *data, int index, int count)
1554{
1555 int source = data->temp_src[index];
1556 int nr;
1557
1558 for (nr = 0; nr < count; nr++) {
1559 int src;
1560
1561 src = nct6775_read_value(data,
1562 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1563 if (src == source)
1564 return nr;
1565 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001566 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001567}
1568
1569static ssize_t
1570show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1571{
1572 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1573 struct nct6775_data *data = nct6775_update_device(dev);
1574 unsigned int alarm = 0;
1575 int nr;
1576
1577 /*
1578 * For temperatures, there is no fixed mapping from registers to alarm
1579 * bits. Alarm bits are determined by the temperature source mapping.
1580 */
1581 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1582 if (nr >= 0) {
1583 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1584 alarm = (data->alarms >> bit) & 0x01;
1585 }
1586 return sprintf(buf, "%u\n", alarm);
1587}
1588
Guenter Roeck30846992013-06-24 22:21:59 -07001589static ssize_t
1590show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1591{
1592 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1593 struct nct6775_data *data = nct6775_update_device(dev);
1594 int nr = data->BEEP_BITS[sattr->index];
1595
1596 return sprintf(buf, "%u\n",
1597 (unsigned int)((data->beeps >> nr) & 0x01));
1598}
1599
1600static ssize_t
1601store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1602 size_t count)
1603{
1604 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1605 struct nct6775_data *data = dev_get_drvdata(dev);
1606 int nr = data->BEEP_BITS[sattr->index];
1607 int regindex = nr >> 3;
1608 unsigned long val;
1609
1610 int err = kstrtoul(buf, 10, &val);
1611 if (err < 0)
1612 return err;
1613 if (val > 1)
1614 return -EINVAL;
1615
1616 mutex_lock(&data->update_lock);
1617 if (val)
1618 data->beeps |= (1ULL << nr);
1619 else
1620 data->beeps &= ~(1ULL << nr);
1621 nct6775_write_value(data, data->REG_BEEP[regindex],
1622 (data->beeps >> (regindex << 3)) & 0xff);
1623 mutex_unlock(&data->update_lock);
1624 return count;
1625}
1626
1627static ssize_t
1628show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1629{
1630 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1631 struct nct6775_data *data = nct6775_update_device(dev);
1632 unsigned int beep = 0;
1633 int nr;
1634
1635 /*
1636 * For temperatures, there is no fixed mapping from registers to beep
1637 * enable bits. Beep enable bits are determined by the temperature
1638 * source mapping.
1639 */
1640 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1641 if (nr >= 0) {
1642 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1643 beep = (data->beeps >> bit) & 0x01;
1644 }
1645 return sprintf(buf, "%u\n", beep);
1646}
1647
1648static ssize_t
1649store_temp_beep(struct device *dev, struct device_attribute *attr,
1650 const char *buf, size_t count)
1651{
1652 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1653 struct nct6775_data *data = dev_get_drvdata(dev);
1654 int nr, bit, regindex;
1655 unsigned long val;
1656
1657 int err = kstrtoul(buf, 10, &val);
1658 if (err < 0)
1659 return err;
1660 if (val > 1)
1661 return -EINVAL;
1662
1663 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1664 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001665 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001666
1667 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1668 regindex = bit >> 3;
1669
1670 mutex_lock(&data->update_lock);
1671 if (val)
1672 data->beeps |= (1ULL << bit);
1673 else
1674 data->beeps &= ~(1ULL << bit);
1675 nct6775_write_value(data, data->REG_BEEP[regindex],
1676 (data->beeps >> (regindex << 3)) & 0xff);
1677 mutex_unlock(&data->update_lock);
1678
1679 return count;
1680}
1681
Guenter Roeckf73cf632013-03-18 09:22:50 -07001682static umode_t nct6775_in_is_visible(struct kobject *kobj,
1683 struct attribute *attr, int index)
1684{
1685 struct device *dev = container_of(kobj, struct device, kobj);
1686 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001687 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001688
Guenter Roeckf73cf632013-03-18 09:22:50 -07001689 if (!(data->have_in & (1 << in)))
1690 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001691
Guenter Roeckf73cf632013-03-18 09:22:50 -07001692 return attr->mode;
1693}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001694
Guenter Roeckf73cf632013-03-18 09:22:50 -07001695SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1696SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001697SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1698 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001699SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1700 store_in_reg, 0, 1);
1701SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1702 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001703
Guenter Roeckf73cf632013-03-18 09:22:50 -07001704/*
1705 * nct6775_in_is_visible uses the index into the following array
1706 * to determine if attributes should be created or not.
1707 * Any change in order or content must be matched.
1708 */
1709static struct sensor_device_template *nct6775_attributes_in_template[] = {
1710 &sensor_dev_template_in_input,
1711 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001712 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001713 &sensor_dev_template_in_min,
1714 &sensor_dev_template_in_max,
1715 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001716};
1717
Guenter Roeckf73cf632013-03-18 09:22:50 -07001718static struct sensor_template_group nct6775_in_template_group = {
1719 .templates = nct6775_attributes_in_template,
1720 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001721};
1722
1723static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001724show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1725{
1726 struct nct6775_data *data = nct6775_update_device(dev);
1727 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1728 int nr = sattr->index;
1729 return sprintf(buf, "%d\n", data->rpm[nr]);
1730}
1731
1732static ssize_t
1733show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1734{
1735 struct nct6775_data *data = nct6775_update_device(dev);
1736 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1737 int nr = sattr->index;
1738 return sprintf(buf, "%d\n",
1739 data->fan_from_reg_min(data->fan_min[nr],
1740 data->fan_div[nr]));
1741}
1742
1743static ssize_t
1744show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1745{
1746 struct nct6775_data *data = nct6775_update_device(dev);
1747 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1748 int nr = sattr->index;
1749 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1750}
1751
1752static ssize_t
1753store_fan_min(struct device *dev, struct device_attribute *attr,
1754 const char *buf, size_t count)
1755{
1756 struct nct6775_data *data = dev_get_drvdata(dev);
1757 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1758 int nr = sattr->index;
1759 unsigned long val;
1760 int err;
1761 unsigned int reg;
1762 u8 new_div;
1763
1764 err = kstrtoul(buf, 10, &val);
1765 if (err < 0)
1766 return err;
1767
1768 mutex_lock(&data->update_lock);
1769 if (!data->has_fan_div) {
1770 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1771 if (!val) {
1772 val = 0xff1f;
1773 } else {
1774 if (val > 1350000U)
1775 val = 135000U;
1776 val = 1350000U / val;
1777 val = (val & 0x1f) | ((val << 3) & 0xff00);
1778 }
1779 data->fan_min[nr] = val;
1780 goto write_min; /* Leave fan divider alone */
1781 }
1782 if (!val) {
1783 /* No min limit, alarm disabled */
1784 data->fan_min[nr] = 255;
1785 new_div = data->fan_div[nr]; /* No change */
1786 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1787 goto write_div;
1788 }
1789 reg = 1350000U / val;
1790 if (reg >= 128 * 255) {
1791 /*
1792 * Speed below this value cannot possibly be represented,
1793 * even with the highest divider (128)
1794 */
1795 data->fan_min[nr] = 254;
1796 new_div = 7; /* 128 == (1 << 7) */
1797 dev_warn(dev,
1798 "fan%u low limit %lu below minimum %u, set to minimum\n",
1799 nr + 1, val, data->fan_from_reg_min(254, 7));
1800 } else if (!reg) {
1801 /*
1802 * Speed above this value cannot possibly be represented,
1803 * even with the lowest divider (1)
1804 */
1805 data->fan_min[nr] = 1;
1806 new_div = 0; /* 1 == (1 << 0) */
1807 dev_warn(dev,
1808 "fan%u low limit %lu above maximum %u, set to maximum\n",
1809 nr + 1, val, data->fan_from_reg_min(1, 0));
1810 } else {
1811 /*
1812 * Automatically pick the best divider, i.e. the one such
1813 * that the min limit will correspond to a register value
1814 * in the 96..192 range
1815 */
1816 new_div = 0;
1817 while (reg > 192 && new_div < 7) {
1818 reg >>= 1;
1819 new_div++;
1820 }
1821 data->fan_min[nr] = reg;
1822 }
1823
1824write_div:
1825 /*
1826 * Write both the fan clock divider (if it changed) and the new
1827 * fan min (unconditionally)
1828 */
1829 if (new_div != data->fan_div[nr]) {
1830 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1831 nr + 1, div_from_reg(data->fan_div[nr]),
1832 div_from_reg(new_div));
1833 data->fan_div[nr] = new_div;
1834 nct6775_write_fan_div_common(data, nr);
1835 /* Give the chip time to sample a new speed value */
1836 data->last_updated = jiffies;
1837 }
1838
1839write_min:
1840 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1841 mutex_unlock(&data->update_lock);
1842
1843 return count;
1844}
1845
Guenter Roeck5c25d952012-12-11 07:29:06 -08001846static ssize_t
1847show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1848{
1849 struct nct6775_data *data = nct6775_update_device(dev);
1850 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1851 int p = data->fan_pulses[sattr->index];
1852
1853 return sprintf(buf, "%d\n", p ? : 4);
1854}
1855
1856static ssize_t
1857store_fan_pulses(struct device *dev, struct device_attribute *attr,
1858 const char *buf, size_t count)
1859{
1860 struct nct6775_data *data = dev_get_drvdata(dev);
1861 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1862 int nr = sattr->index;
1863 unsigned long val;
1864 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001865 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001866
1867 err = kstrtoul(buf, 10, &val);
1868 if (err < 0)
1869 return err;
1870
1871 if (val > 4)
1872 return -EINVAL;
1873
1874 mutex_lock(&data->update_lock);
1875 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001876 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1877 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1878 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1879 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001880 mutex_unlock(&data->update_lock);
1881
1882 return count;
1883}
1884
Guenter Roeckf73cf632013-03-18 09:22:50 -07001885static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1886 struct attribute *attr, int index)
1887{
1888 struct device *dev = container_of(kobj, struct device, kobj);
1889 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001890 int fan = index / 6; /* fan index */
1891 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001892
1893 if (!(data->has_fan & (1 << fan)))
1894 return 0;
1895
1896 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1897 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001898 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001899 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001900 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1901 return 0;
1902 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001903 return 0;
1904
1905 return attr->mode;
1906}
1907
1908SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1909SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1910 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001911SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1912 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001913SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1914 store_fan_pulses, 0);
1915SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1916 store_fan_min, 0);
1917SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1918
1919/*
1920 * nct6775_fan_is_visible uses the index into the following array
1921 * to determine if attributes should be created or not.
1922 * Any change in order or content must be matched.
1923 */
1924static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1925 &sensor_dev_template_fan_input,
1926 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001927 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001928 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001929 &sensor_dev_template_fan_min, /* 4 */
1930 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001931 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001932};
1933
Guenter Roeckf73cf632013-03-18 09:22:50 -07001934static struct sensor_template_group nct6775_fan_template_group = {
1935 .templates = nct6775_attributes_fan_template,
1936 .is_visible = nct6775_fan_is_visible,
1937 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001938};
1939
1940static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001941show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1942{
1943 struct nct6775_data *data = nct6775_update_device(dev);
1944 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1945 int nr = sattr->index;
1946 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1947}
1948
1949static ssize_t
1950show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1951{
1952 struct nct6775_data *data = nct6775_update_device(dev);
1953 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1954 int nr = sattr->nr;
1955 int index = sattr->index;
1956
1957 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1958}
1959
1960static ssize_t
1961store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1962 size_t count)
1963{
1964 struct nct6775_data *data = dev_get_drvdata(dev);
1965 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1966 int nr = sattr->nr;
1967 int index = sattr->index;
1968 int err;
1969 long val;
1970
1971 err = kstrtol(buf, 10, &val);
1972 if (err < 0)
1973 return err;
1974
1975 mutex_lock(&data->update_lock);
1976 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1977 nct6775_write_temp(data, data->reg_temp[index][nr],
1978 data->temp[index][nr]);
1979 mutex_unlock(&data->update_lock);
1980 return count;
1981}
1982
1983static ssize_t
1984show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1985{
1986 struct nct6775_data *data = nct6775_update_device(dev);
1987 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1988
1989 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1990}
1991
1992static ssize_t
1993store_temp_offset(struct device *dev, struct device_attribute *attr,
1994 const char *buf, size_t count)
1995{
1996 struct nct6775_data *data = dev_get_drvdata(dev);
1997 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1998 int nr = sattr->index;
1999 long val;
2000 int err;
2001
2002 err = kstrtol(buf, 10, &val);
2003 if (err < 0)
2004 return err;
2005
2006 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
2007
2008 mutex_lock(&data->update_lock);
2009 data->temp_offset[nr] = val;
2010 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
2011 mutex_unlock(&data->update_lock);
2012
2013 return count;
2014}
2015
2016static ssize_t
2017show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2018{
2019 struct nct6775_data *data = nct6775_update_device(dev);
2020 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2021 int nr = sattr->index;
2022 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2023}
2024
2025static ssize_t
2026store_temp_type(struct device *dev, struct device_attribute *attr,
2027 const char *buf, size_t count)
2028{
2029 struct nct6775_data *data = nct6775_update_device(dev);
2030 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2031 int nr = sattr->index;
2032 unsigned long val;
2033 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002034 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002035
2036 err = kstrtoul(buf, 10, &val);
2037 if (err < 0)
2038 return err;
2039
2040 if (val != 1 && val != 3 && val != 4)
2041 return -EINVAL;
2042
2043 mutex_lock(&data->update_lock);
2044
2045 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002046 vbit = 0x02 << nr;
2047 dbit = data->DIODE_MASK << nr;
2048 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2049 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002050 switch (val) {
2051 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002052 vbat |= vbit;
2053 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002054 break;
2055 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002056 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002057 break;
2058 case 4: /* thermistor */
2059 break;
2060 }
2061 nct6775_write_value(data, data->REG_VBAT, vbat);
2062 nct6775_write_value(data, data->REG_DIODE, diode);
2063
2064 mutex_unlock(&data->update_lock);
2065 return count;
2066}
2067
Guenter Roeckf73cf632013-03-18 09:22:50 -07002068static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2069 struct attribute *attr, int index)
2070{
2071 struct device *dev = container_of(kobj, struct device, kobj);
2072 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002073 int temp = index / 10; /* temp index */
2074 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002075
2076 if (!(data->have_temp & (1 << temp)))
2077 return 0;
2078
2079 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2080 return 0; /* alarm */
2081
Guenter Roeck30846992013-06-24 22:21:59 -07002082 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2083 return 0; /* beep */
2084
2085 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002086 return 0;
2087
Guenter Roeck30846992013-06-24 22:21:59 -07002088 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002089 return 0;
2090
Guenter Roeck30846992013-06-24 22:21:59 -07002091 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002092 return 0;
2093
Guenter Roeck30846992013-06-24 22:21:59 -07002094 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002095 return 0;
2096
2097 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002098 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002099 return 0;
2100
2101 return attr->mode;
2102}
2103
2104SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2105SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2106SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2107 store_temp, 0, 1);
2108SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2109 show_temp, store_temp, 0, 2);
2110SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2111 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002112SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2113 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002114SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2115 show_temp_offset, store_temp_offset, 0);
2116SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2117 store_temp_type, 0);
2118SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002119SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2120 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002121
2122/*
2123 * nct6775_temp_is_visible uses the index into the following array
2124 * to determine if attributes should be created or not.
2125 * Any change in order or content must be matched.
2126 */
2127static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2128 &sensor_dev_template_temp_input,
2129 &sensor_dev_template_temp_label,
2130 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002131 &sensor_dev_template_temp_beep, /* 3 */
2132 &sensor_dev_template_temp_max, /* 4 */
2133 &sensor_dev_template_temp_max_hyst, /* 5 */
2134 &sensor_dev_template_temp_crit, /* 6 */
2135 &sensor_dev_template_temp_lcrit, /* 7 */
2136 &sensor_dev_template_temp_offset, /* 8 */
2137 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002138 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002139};
2140
Guenter Roeckf73cf632013-03-18 09:22:50 -07002141static struct sensor_template_group nct6775_temp_template_group = {
2142 .templates = nct6775_attributes_temp_template,
2143 .is_visible = nct6775_temp_is_visible,
2144 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002145};
2146
Guenter Roeckaa136e52012-12-04 03:26:05 -08002147static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002148show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2149{
2150 struct nct6775_data *data = nct6775_update_device(dev);
2151 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2152
2153 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2154}
2155
2156static ssize_t
2157store_pwm_mode(struct device *dev, struct device_attribute *attr,
2158 const char *buf, size_t count)
2159{
2160 struct nct6775_data *data = dev_get_drvdata(dev);
2161 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2162 int nr = sattr->index;
2163 unsigned long val;
2164 int err;
2165 u8 reg;
2166
2167 err = kstrtoul(buf, 10, &val);
2168 if (err < 0)
2169 return err;
2170
2171 if (val > 1)
2172 return -EINVAL;
2173
2174 /* Setting DC mode is not supported for all chips/channels */
2175 if (data->REG_PWM_MODE[nr] == 0) {
2176 if (val)
2177 return -EINVAL;
2178 return count;
2179 }
2180
2181 mutex_lock(&data->update_lock);
2182 data->pwm_mode[nr] = val;
2183 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2184 reg &= ~data->PWM_MODE_MASK[nr];
2185 if (val)
2186 reg |= data->PWM_MODE_MASK[nr];
2187 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2188 mutex_unlock(&data->update_lock);
2189 return count;
2190}
2191
2192static ssize_t
2193show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2194{
2195 struct nct6775_data *data = nct6775_update_device(dev);
2196 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2197 int nr = sattr->nr;
2198 int index = sattr->index;
2199 int pwm;
2200
2201 /*
2202 * For automatic fan control modes, show current pwm readings.
2203 * Otherwise, show the configured value.
2204 */
2205 if (index == 0 && data->pwm_enable[nr] > manual)
2206 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2207 else
2208 pwm = data->pwm[index][nr];
2209
2210 return sprintf(buf, "%d\n", pwm);
2211}
2212
2213static ssize_t
2214store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2215 size_t count)
2216{
2217 struct nct6775_data *data = dev_get_drvdata(dev);
2218 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2219 int nr = sattr->nr;
2220 int index = sattr->index;
2221 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002222 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2223 int maxval[7]
2224 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002225 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002226 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002227
2228 err = kstrtoul(buf, 10, &val);
2229 if (err < 0)
2230 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002231 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002232
2233 mutex_lock(&data->update_lock);
2234 data->pwm[index][nr] = val;
2235 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002236 if (index == 2) { /* floor: disable if val == 0 */
2237 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2238 reg &= 0x7f;
2239 if (val)
2240 reg |= 0x80;
2241 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2242 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002243 mutex_unlock(&data->update_lock);
2244 return count;
2245}
2246
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002247/* Returns 0 if OK, -EINVAL otherwise */
2248static int check_trip_points(struct nct6775_data *data, int nr)
2249{
2250 int i;
2251
2252 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2253 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2254 return -EINVAL;
2255 }
2256 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2257 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2258 return -EINVAL;
2259 }
2260 /* validate critical temperature and pwm if enabled (pwm > 0) */
2261 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2262 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2263 data->auto_temp[nr][data->auto_pwm_num] ||
2264 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2265 data->auto_pwm[nr][data->auto_pwm_num])
2266 return -EINVAL;
2267 }
2268 return 0;
2269}
2270
2271static void pwm_update_registers(struct nct6775_data *data, int nr)
2272{
2273 u8 reg;
2274
2275 switch (data->pwm_enable[nr]) {
2276 case off:
2277 case manual:
2278 break;
2279 case speed_cruise:
2280 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2281 reg = (reg & ~data->tolerance_mask) |
2282 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2283 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2284 nct6775_write_value(data, data->REG_TARGET[nr],
2285 data->target_speed[nr] & 0xff);
2286 if (data->REG_TOLERANCE_H) {
2287 reg = (data->target_speed[nr] >> 8) & 0x0f;
2288 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2289 nct6775_write_value(data,
2290 data->REG_TOLERANCE_H[nr],
2291 reg);
2292 }
2293 break;
2294 case thermal_cruise:
2295 nct6775_write_value(data, data->REG_TARGET[nr],
2296 data->target_temp[nr]);
2297 /* intentional */
2298 default:
2299 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2300 reg = (reg & ~data->tolerance_mask) |
2301 data->temp_tolerance[0][nr];
2302 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2303 break;
2304 }
2305}
2306
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002307static ssize_t
2308show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2309{
2310 struct nct6775_data *data = nct6775_update_device(dev);
2311 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2312
2313 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2314}
2315
2316static ssize_t
2317store_pwm_enable(struct device *dev, struct device_attribute *attr,
2318 const char *buf, size_t count)
2319{
2320 struct nct6775_data *data = dev_get_drvdata(dev);
2321 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2322 int nr = sattr->index;
2323 unsigned long val;
2324 int err;
2325 u16 reg;
2326
2327 err = kstrtoul(buf, 10, &val);
2328 if (err < 0)
2329 return err;
2330
2331 if (val > sf4)
2332 return -EINVAL;
2333
2334 if (val == sf3 && data->kind != nct6775)
2335 return -EINVAL;
2336
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002337 if (val == sf4 && check_trip_points(data, nr)) {
2338 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2339 dev_err(dev, "Adjust trip points and try again\n");
2340 return -EINVAL;
2341 }
2342
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002343 mutex_lock(&data->update_lock);
2344 data->pwm_enable[nr] = val;
2345 if (val == off) {
2346 /*
2347 * turn off pwm control: select manual mode, set pwm to maximum
2348 */
2349 data->pwm[0][nr] = 255;
2350 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2351 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002352 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002353 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2354 reg &= 0x0f;
2355 reg |= pwm_enable_to_reg(val) << 4;
2356 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2357 mutex_unlock(&data->update_lock);
2358 return count;
2359}
2360
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002361static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002362show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002363{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002364 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002365
2366 for (i = 0; i < NUM_TEMP; i++) {
2367 if (!(data->have_temp & (1 << i)))
2368 continue;
2369 if (src == data->temp_src[i]) {
2370 sel = i + 1;
2371 break;
2372 }
2373 }
2374
2375 return sprintf(buf, "%d\n", sel);
2376}
2377
2378static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002379show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2380{
2381 struct nct6775_data *data = nct6775_update_device(dev);
2382 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2383 int index = sattr->index;
2384
2385 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2386}
2387
2388static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002389store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2390 const char *buf, size_t count)
2391{
2392 struct nct6775_data *data = nct6775_update_device(dev);
2393 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2394 int nr = sattr->index;
2395 unsigned long val;
2396 int err, reg, src;
2397
2398 err = kstrtoul(buf, 10, &val);
2399 if (err < 0)
2400 return err;
2401 if (val == 0 || val > NUM_TEMP)
2402 return -EINVAL;
2403 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2404 return -EINVAL;
2405
2406 mutex_lock(&data->update_lock);
2407 src = data->temp_src[val - 1];
2408 data->pwm_temp_sel[nr] = src;
2409 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2410 reg &= 0xe0;
2411 reg |= src;
2412 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2413 mutex_unlock(&data->update_lock);
2414
2415 return count;
2416}
2417
2418static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002419show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2420 char *buf)
2421{
2422 struct nct6775_data *data = nct6775_update_device(dev);
2423 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2424 int index = sattr->index;
2425
2426 return show_pwm_temp_sel_common(data, buf,
2427 data->pwm_weight_temp_sel[index]);
2428}
2429
2430static ssize_t
2431store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2432 const char *buf, size_t count)
2433{
2434 struct nct6775_data *data = nct6775_update_device(dev);
2435 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2436 int nr = sattr->index;
2437 unsigned long val;
2438 int err, reg, src;
2439
2440 err = kstrtoul(buf, 10, &val);
2441 if (err < 0)
2442 return err;
2443 if (val > NUM_TEMP)
2444 return -EINVAL;
2445 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2446 !data->temp_src[val - 1]))
2447 return -EINVAL;
2448
2449 mutex_lock(&data->update_lock);
2450 if (val) {
2451 src = data->temp_src[val - 1];
2452 data->pwm_weight_temp_sel[nr] = src;
2453 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2454 reg &= 0xe0;
2455 reg |= (src | 0x80);
2456 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2457 } else {
2458 data->pwm_weight_temp_sel[nr] = 0;
2459 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2460 reg &= 0x7f;
2461 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2462 }
2463 mutex_unlock(&data->update_lock);
2464
2465 return count;
2466}
2467
2468static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002469show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2470{
2471 struct nct6775_data *data = nct6775_update_device(dev);
2472 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2473
2474 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2475}
2476
2477static ssize_t
2478store_target_temp(struct device *dev, struct device_attribute *attr,
2479 const char *buf, size_t count)
2480{
2481 struct nct6775_data *data = dev_get_drvdata(dev);
2482 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2483 int nr = sattr->index;
2484 unsigned long val;
2485 int err;
2486
2487 err = kstrtoul(buf, 10, &val);
2488 if (err < 0)
2489 return err;
2490
2491 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2492 data->target_temp_mask);
2493
2494 mutex_lock(&data->update_lock);
2495 data->target_temp[nr] = val;
2496 pwm_update_registers(data, nr);
2497 mutex_unlock(&data->update_lock);
2498 return count;
2499}
2500
2501static ssize_t
2502show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2503{
2504 struct nct6775_data *data = nct6775_update_device(dev);
2505 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2506 int nr = sattr->index;
2507
2508 return sprintf(buf, "%d\n",
2509 fan_from_reg16(data->target_speed[nr],
2510 data->fan_div[nr]));
2511}
2512
2513static ssize_t
2514store_target_speed(struct device *dev, struct device_attribute *attr,
2515 const char *buf, size_t count)
2516{
2517 struct nct6775_data *data = dev_get_drvdata(dev);
2518 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2519 int nr = sattr->index;
2520 unsigned long val;
2521 int err;
2522 u16 speed;
2523
2524 err = kstrtoul(buf, 10, &val);
2525 if (err < 0)
2526 return err;
2527
2528 val = clamp_val(val, 0, 1350000U);
2529 speed = fan_to_reg(val, data->fan_div[nr]);
2530
2531 mutex_lock(&data->update_lock);
2532 data->target_speed[nr] = speed;
2533 pwm_update_registers(data, nr);
2534 mutex_unlock(&data->update_lock);
2535 return count;
2536}
2537
2538static ssize_t
2539show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2540 char *buf)
2541{
2542 struct nct6775_data *data = nct6775_update_device(dev);
2543 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2544 int nr = sattr->nr;
2545 int index = sattr->index;
2546
2547 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2548}
2549
2550static ssize_t
2551store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2552 const char *buf, size_t count)
2553{
2554 struct nct6775_data *data = dev_get_drvdata(dev);
2555 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2556 int nr = sattr->nr;
2557 int index = sattr->index;
2558 unsigned long val;
2559 int err;
2560
2561 err = kstrtoul(buf, 10, &val);
2562 if (err < 0)
2563 return err;
2564
2565 /* Limit tolerance as needed */
2566 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2567
2568 mutex_lock(&data->update_lock);
2569 data->temp_tolerance[index][nr] = val;
2570 if (index)
2571 pwm_update_registers(data, nr);
2572 else
2573 nct6775_write_value(data,
2574 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2575 val);
2576 mutex_unlock(&data->update_lock);
2577 return count;
2578}
2579
2580/*
2581 * Fan speed tolerance is a tricky beast, since the associated register is
2582 * a tick counter, but the value is reported and configured as rpm.
2583 * Compute resulting low and high rpm values and report the difference.
2584 */
2585static ssize_t
2586show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2587 char *buf)
2588{
2589 struct nct6775_data *data = nct6775_update_device(dev);
2590 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2591 int nr = sattr->index;
2592 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2593 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2594 int tolerance;
2595
2596 if (low <= 0)
2597 low = 1;
2598 if (high > 0xffff)
2599 high = 0xffff;
2600 if (high < low)
2601 high = low;
2602
2603 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2604 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2605
2606 return sprintf(buf, "%d\n", tolerance);
2607}
2608
2609static ssize_t
2610store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2611 const char *buf, size_t count)
2612{
2613 struct nct6775_data *data = dev_get_drvdata(dev);
2614 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2615 int nr = sattr->index;
2616 unsigned long val;
2617 int err;
2618 int low, high;
2619
2620 err = kstrtoul(buf, 10, &val);
2621 if (err < 0)
2622 return err;
2623
2624 high = fan_from_reg16(data->target_speed[nr],
2625 data->fan_div[nr]) + val;
2626 low = fan_from_reg16(data->target_speed[nr],
2627 data->fan_div[nr]) - val;
2628 if (low <= 0)
2629 low = 1;
2630 if (high < low)
2631 high = low;
2632
2633 val = (fan_to_reg(low, data->fan_div[nr]) -
2634 fan_to_reg(high, data->fan_div[nr])) / 2;
2635
2636 /* Limit tolerance as needed */
2637 val = clamp_val(val, 0, data->speed_tolerance_limit);
2638
2639 mutex_lock(&data->update_lock);
2640 data->target_speed_tolerance[nr] = val;
2641 pwm_update_registers(data, nr);
2642 mutex_unlock(&data->update_lock);
2643 return count;
2644}
2645
Guenter Roeckf73cf632013-03-18 09:22:50 -07002646SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2647SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2648 store_pwm_mode, 0);
2649SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2650 store_pwm_enable, 0);
2651SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2652 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2653SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2654 show_target_temp, store_target_temp, 0);
2655SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2656 show_target_speed, store_target_speed, 0);
2657SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2658 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002659
2660/* Smart Fan registers */
2661
2662static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002663show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2664{
2665 struct nct6775_data *data = nct6775_update_device(dev);
2666 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2667 int nr = sattr->nr;
2668 int index = sattr->index;
2669
2670 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2671}
2672
2673static ssize_t
2674store_weight_temp(struct device *dev, struct device_attribute *attr,
2675 const char *buf, size_t count)
2676{
2677 struct nct6775_data *data = dev_get_drvdata(dev);
2678 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2679 int nr = sattr->nr;
2680 int index = sattr->index;
2681 unsigned long val;
2682 int err;
2683
2684 err = kstrtoul(buf, 10, &val);
2685 if (err < 0)
2686 return err;
2687
2688 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2689
2690 mutex_lock(&data->update_lock);
2691 data->weight_temp[index][nr] = val;
2692 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2693 mutex_unlock(&data->update_lock);
2694 return count;
2695}
2696
Guenter Roeckf73cf632013-03-18 09:22:50 -07002697SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2698 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2699SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2700 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2701SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2702 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2703SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2704 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2705SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2706 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2707SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2708 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002709
2710static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002711show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2712{
2713 struct nct6775_data *data = nct6775_update_device(dev);
2714 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2715 int nr = sattr->nr;
2716 int index = sattr->index;
2717
2718 return sprintf(buf, "%d\n",
2719 step_time_from_reg(data->fan_time[index][nr],
2720 data->pwm_mode[nr]));
2721}
2722
2723static ssize_t
2724store_fan_time(struct device *dev, struct device_attribute *attr,
2725 const char *buf, size_t count)
2726{
2727 struct nct6775_data *data = dev_get_drvdata(dev);
2728 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2729 int nr = sattr->nr;
2730 int index = sattr->index;
2731 unsigned long val;
2732 int err;
2733
2734 err = kstrtoul(buf, 10, &val);
2735 if (err < 0)
2736 return err;
2737
2738 val = step_time_to_reg(val, data->pwm_mode[nr]);
2739 mutex_lock(&data->update_lock);
2740 data->fan_time[index][nr] = val;
2741 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2742 mutex_unlock(&data->update_lock);
2743 return count;
2744}
2745
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002746static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002747show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2748{
2749 struct nct6775_data *data = nct6775_update_device(dev);
2750 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2751
2752 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2753}
2754
2755static ssize_t
2756store_auto_pwm(struct device *dev, struct device_attribute *attr,
2757 const char *buf, size_t count)
2758{
2759 struct nct6775_data *data = dev_get_drvdata(dev);
2760 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2761 int nr = sattr->nr;
2762 int point = sattr->index;
2763 unsigned long val;
2764 int err;
2765 u8 reg;
2766
2767 err = kstrtoul(buf, 10, &val);
2768 if (err < 0)
2769 return err;
2770 if (val > 255)
2771 return -EINVAL;
2772
2773 if (point == data->auto_pwm_num) {
2774 if (data->kind != nct6775 && !val)
2775 return -EINVAL;
2776 if (data->kind != nct6779 && val)
2777 val = 0xff;
2778 }
2779
2780 mutex_lock(&data->update_lock);
2781 data->auto_pwm[nr][point] = val;
2782 if (point < data->auto_pwm_num) {
2783 nct6775_write_value(data,
2784 NCT6775_AUTO_PWM(data, nr, point),
2785 data->auto_pwm[nr][point]);
2786 } else {
2787 switch (data->kind) {
2788 case nct6775:
2789 /* disable if needed (pwm == 0) */
2790 reg = nct6775_read_value(data,
2791 NCT6775_REG_CRITICAL_ENAB[nr]);
2792 if (val)
2793 reg |= 0x02;
2794 else
2795 reg &= ~0x02;
2796 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2797 reg);
2798 break;
2799 case nct6776:
2800 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002801 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002802 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002803 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08002804 case nct6792:
Guenter Roeck6c009502012-07-01 08:23:15 -07002805 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002806 val);
2807 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002808 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002809 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002810 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002811 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002812 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002813 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002814 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002815 reg);
2816 break;
2817 }
2818 }
2819 mutex_unlock(&data->update_lock);
2820 return count;
2821}
2822
2823static ssize_t
2824show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2825{
2826 struct nct6775_data *data = nct6775_update_device(dev);
2827 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2828 int nr = sattr->nr;
2829 int point = sattr->index;
2830
2831 /*
2832 * We don't know for sure if the temperature is signed or unsigned.
2833 * Assume it is unsigned.
2834 */
2835 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2836}
2837
2838static ssize_t
2839store_auto_temp(struct device *dev, struct device_attribute *attr,
2840 const char *buf, size_t count)
2841{
2842 struct nct6775_data *data = dev_get_drvdata(dev);
2843 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2844 int nr = sattr->nr;
2845 int point = sattr->index;
2846 unsigned long val;
2847 int err;
2848
2849 err = kstrtoul(buf, 10, &val);
2850 if (err)
2851 return err;
2852 if (val > 255000)
2853 return -EINVAL;
2854
2855 mutex_lock(&data->update_lock);
2856 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2857 if (point < data->auto_pwm_num) {
2858 nct6775_write_value(data,
2859 NCT6775_AUTO_TEMP(data, nr, point),
2860 data->auto_temp[nr][point]);
2861 } else {
2862 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2863 data->auto_temp[nr][point]);
2864 }
2865 mutex_unlock(&data->update_lock);
2866 return count;
2867}
2868
Guenter Roeckf73cf632013-03-18 09:22:50 -07002869static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2870 struct attribute *attr, int index)
2871{
2872 struct device *dev = container_of(kobj, struct device, kobj);
2873 struct nct6775_data *data = dev_get_drvdata(dev);
2874 int pwm = index / 36; /* pwm index */
2875 int nr = index % 36; /* attribute index */
2876
2877 if (!(data->has_pwm & (1 << pwm)))
2878 return 0;
2879
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002880 if ((nr >= 14 && nr <= 18) || nr == 21) /* weight */
2881 if (!data->REG_WEIGHT_TEMP_SEL[pwm])
2882 return 0;
Guenter Roeckf73cf632013-03-18 09:22:50 -07002883 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2884 return 0;
2885 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2886 return 0;
2887 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2888 return 0;
2889
2890 if (nr >= 22 && nr <= 35) { /* auto point */
2891 int api = (nr - 22) / 2; /* auto point index */
2892
2893 if (api > data->auto_pwm_num)
2894 return 0;
2895 }
2896 return attr->mode;
2897}
2898
2899SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2900 show_fan_time, store_fan_time, 0, 0);
2901SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2902 show_fan_time, store_fan_time, 0, 1);
2903SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2904 show_fan_time, store_fan_time, 0, 2);
2905SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2906 store_pwm, 0, 1);
2907SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2908 store_pwm, 0, 2);
2909SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2910 show_temp_tolerance, store_temp_tolerance, 0, 0);
2911SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2912 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2913 0, 1);
2914
2915SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2916 0, 3);
2917
2918SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2919 store_pwm, 0, 4);
2920
2921SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2922 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2923SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2924 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2925
2926SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2927 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2928SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2929 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2930
2931SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2932 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2933SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2934 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2935
2936SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2937 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2938SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2939 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2940
2941SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2942 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2943SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2944 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2945
2946SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2947 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2948SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2949 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2950
2951SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2952 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2953SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2954 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2955
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002956/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002957 * nct6775_pwm_is_visible uses the index into the following array
2958 * to determine if attributes should be created or not.
2959 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002960 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002961static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2962 &sensor_dev_template_pwm,
2963 &sensor_dev_template_pwm_mode,
2964 &sensor_dev_template_pwm_enable,
2965 &sensor_dev_template_pwm_temp_sel,
2966 &sensor_dev_template_pwm_temp_tolerance,
2967 &sensor_dev_template_pwm_crit_temp_tolerance,
2968 &sensor_dev_template_pwm_target_temp,
2969 &sensor_dev_template_fan_target,
2970 &sensor_dev_template_fan_tolerance,
2971 &sensor_dev_template_pwm_stop_time,
2972 &sensor_dev_template_pwm_step_up_time,
2973 &sensor_dev_template_pwm_step_down_time,
2974 &sensor_dev_template_pwm_start,
2975 &sensor_dev_template_pwm_floor,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002976 &sensor_dev_template_pwm_weight_temp_sel, /* 14 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002977 &sensor_dev_template_pwm_weight_temp_step,
2978 &sensor_dev_template_pwm_weight_temp_step_tol,
2979 &sensor_dev_template_pwm_weight_temp_step_base,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002980 &sensor_dev_template_pwm_weight_duty_step, /* 18 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002981 &sensor_dev_template_pwm_max, /* 19 */
2982 &sensor_dev_template_pwm_step, /* 20 */
2983 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2984 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2985 &sensor_dev_template_pwm_auto_point1_temp,
2986 &sensor_dev_template_pwm_auto_point2_pwm,
2987 &sensor_dev_template_pwm_auto_point2_temp,
2988 &sensor_dev_template_pwm_auto_point3_pwm,
2989 &sensor_dev_template_pwm_auto_point3_temp,
2990 &sensor_dev_template_pwm_auto_point4_pwm,
2991 &sensor_dev_template_pwm_auto_point4_temp,
2992 &sensor_dev_template_pwm_auto_point5_pwm,
2993 &sensor_dev_template_pwm_auto_point5_temp,
2994 &sensor_dev_template_pwm_auto_point6_pwm,
2995 &sensor_dev_template_pwm_auto_point6_temp,
2996 &sensor_dev_template_pwm_auto_point7_pwm,
2997 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002998
Guenter Roeckf73cf632013-03-18 09:22:50 -07002999 NULL
3000};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003001
Guenter Roeckf73cf632013-03-18 09:22:50 -07003002static struct sensor_template_group nct6775_pwm_template_group = {
3003 .templates = nct6775_attributes_pwm_template,
3004 .is_visible = nct6775_pwm_is_visible,
3005 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003006};
3007
3008static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003009show_vid(struct device *dev, struct device_attribute *attr, char *buf)
3010{
3011 struct nct6775_data *data = dev_get_drvdata(dev);
3012 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3013}
3014
3015static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3016
Guenter Roecka6bd5872012-12-04 03:13:34 -08003017/* Case open detection */
3018
3019static ssize_t
3020clear_caseopen(struct device *dev, struct device_attribute *attr,
3021 const char *buf, size_t count)
3022{
3023 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003024 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3025 unsigned long val;
3026 u8 reg;
3027 int ret;
3028
3029 if (kstrtoul(buf, 10, &val) || val != 0)
3030 return -EINVAL;
3031
3032 mutex_lock(&data->update_lock);
3033
3034 /*
3035 * Use CR registers to clear caseopen status.
3036 * The CR registers are the same for all chips, and not all chips
3037 * support clearing the caseopen status through "regular" registers.
3038 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003039 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003040 if (ret) {
3041 count = ret;
3042 goto error;
3043 }
3044
Guenter Roeckdf612d52013-07-08 13:15:04 -07003045 superio_select(data->sioreg, NCT6775_LD_ACPI);
3046 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003047 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003048 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003049 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003050 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3051 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003052
3053 data->valid = false; /* Force cache refresh */
3054error:
3055 mutex_unlock(&data->update_lock);
3056 return count;
3057}
3058
Guenter Roeckf73cf632013-03-18 09:22:50 -07003059static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3060 clear_caseopen, INTRUSION_ALARM_BASE);
3061static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3062 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003063static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3064 store_beep, INTRUSION_ALARM_BASE);
3065static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3066 store_beep, INTRUSION_ALARM_BASE + 1);
3067static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3068 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003069
3070static umode_t nct6775_other_is_visible(struct kobject *kobj,
3071 struct attribute *attr, int index)
3072{
3073 struct device *dev = container_of(kobj, struct device, kobj);
3074 struct nct6775_data *data = dev_get_drvdata(dev);
3075
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003076 if (index == 0 && !data->have_vid)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003077 return 0;
3078
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003079 if (index == 1 || index == 2) {
3080 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003081 return 0;
3082 }
3083
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003084 if (index == 3 || index == 4) {
3085 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
Guenter Roeck30846992013-06-24 22:21:59 -07003086 return 0;
3087 }
3088
Guenter Roeckf73cf632013-03-18 09:22:50 -07003089 return attr->mode;
3090}
3091
3092/*
3093 * nct6775_other_is_visible uses the index into the following array
3094 * to determine if attributes should be created or not.
3095 * Any change in order or content must be matched.
3096 */
3097static struct attribute *nct6775_attributes_other[] = {
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003098 &dev_attr_cpu0_vid.attr, /* 0 */
3099 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
3100 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
3101 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
3102 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
3103 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003104
3105 NULL
3106};
3107
3108static const struct attribute_group nct6775_group_other = {
3109 .attrs = nct6775_attributes_other,
3110 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003111};
3112
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003113static inline void nct6775_init_device(struct nct6775_data *data)
3114{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003115 int i;
3116 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003117
3118 /* Start monitoring if needed */
3119 if (data->REG_CONFIG) {
3120 tmp = nct6775_read_value(data, data->REG_CONFIG);
3121 if (!(tmp & 0x01))
3122 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3123 }
3124
Guenter Roeckaa136e52012-12-04 03:26:05 -08003125 /* Enable temperature sensors if needed */
3126 for (i = 0; i < NUM_TEMP; i++) {
3127 if (!(data->have_temp & (1 << i)))
3128 continue;
3129 if (!data->reg_temp_config[i])
3130 continue;
3131 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3132 if (tmp & 0x01)
3133 nct6775_write_value(data, data->reg_temp_config[i],
3134 tmp & 0xfe);
3135 }
3136
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003137 /* Enable VBAT monitoring if needed */
3138 tmp = nct6775_read_value(data, data->REG_VBAT);
3139 if (!(tmp & 0x01))
3140 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003141
3142 diode = nct6775_read_value(data, data->REG_DIODE);
3143
3144 for (i = 0; i < data->temp_fixed_num; i++) {
3145 if (!(data->have_temp_fixed & (1 << i)))
3146 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003147 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3148 data->temp_type[i]
3149 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003150 else /* thermistor */
3151 data->temp_type[i] = 4;
3152 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003153}
3154
Guenter Roeckf73cf632013-03-18 09:22:50 -07003155static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003156nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003157{
David Bartley578ab5f2013-06-24 22:28:28 -07003158 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3159 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003160 int sioreg = data->sioreg;
3161 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003162
3163 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3164 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003165 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003166
3167 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003168 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003169
3170 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003171 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003172 fan4min = false;
3173 fan5pin = false;
3174 fan6pin = false;
3175 pwm4pin = false;
3176 pwm5pin = false;
3177 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003178 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003179 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003180
Guenter Roeckdf612d52013-07-08 13:15:04 -07003181 superio_select(sioreg, NCT6775_LD_HWM);
3182 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003183
3184 if (regval & 0x80)
3185 fan3pin = gpok;
3186 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003187 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003188
3189 if (regval & 0x40)
3190 fan4pin = gpok;
3191 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003192 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003193
3194 if (regval & 0x20)
3195 fan5pin = gpok;
3196 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003197 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003198
3199 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003200 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003201 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003202 pwm4pin = false;
3203 pwm5pin = false;
3204 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003205 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003206 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003207 fan3pin = !(regval & 0x80);
3208 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003209
3210 fan4pin = false;
3211 fan4min = false;
3212 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003213 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003214 pwm4pin = false;
3215 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003216 pwm6pin = false;
Guenter Roeck8aefb932014-11-16 09:50:04 -08003217 } else { /* NCT6779D, NCT6791D, or NCT6792D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003218 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003219
3220 fan3pin = !(regval & (1 << 5));
3221 fan4pin = !(regval & (1 << 6));
3222 fan5pin = !(regval & (1 << 7));
3223
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003224 pwm3pin = !(regval & (1 << 0));
3225 pwm4pin = !(regval & (1 << 1));
3226 pwm5pin = !(regval & (1 << 2));
3227
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003228 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003229
Guenter Roeck8aefb932014-11-16 09:50:04 -08003230 if (data->kind == nct6791 || data->kind == nct6792) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003231 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003232 fan6pin = (regval & (1 << 1));
3233 pwm6pin = (regval & (1 << 0));
3234 } else { /* NCT6779D */
3235 fan6pin = false;
3236 pwm6pin = false;
3237 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003238 }
3239
David Bartley578ab5f2013-06-24 22:28:28 -07003240 /* fan 1 and 2 (0x03) are always present */
3241 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3242 (fan5pin << 4) | (fan6pin << 5);
3243 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3244 (fan5pin << 4);
3245 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3246 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003247}
3248
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003249static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3250 int *available, int *mask)
3251{
3252 int i;
3253 u8 src;
3254
3255 for (i = 0; i < data->pwm_num && *available; i++) {
3256 int index;
3257
3258 if (!regp[i])
3259 continue;
3260 src = nct6775_read_value(data, regp[i]);
3261 src &= 0x1f;
3262 if (!src || (*mask & (1 << src)))
3263 continue;
3264 if (src >= data->temp_label_num ||
3265 !strlen(data->temp_label[src]))
3266 continue;
3267
3268 index = __ffs(*available);
3269 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3270 *available &= ~(1 << index);
3271 *mask |= 1 << src;
3272 }
3273}
3274
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003275static int nct6775_probe(struct platform_device *pdev)
3276{
3277 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003278 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003279 struct nct6775_data *data;
3280 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003281 int i, s, err = 0;
3282 int src, mask, available;
3283 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003284 const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003285 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003286 int num_reg_temp, num_reg_temp_mon;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003287 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003288 struct attribute_group *group;
Guenter Roecka150d952013-07-11 22:55:22 -07003289 struct device *hwmon_dev;
Axel Lin55bdee62014-07-24 08:59:34 +08003290 int num_attr_groups = 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003291
3292 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3293 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3294 DRVNAME))
3295 return -EBUSY;
3296
3297 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3298 GFP_KERNEL);
3299 if (!data)
3300 return -ENOMEM;
3301
3302 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003303 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003304 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003305 mutex_init(&data->update_lock);
3306 data->name = nct6775_device_names[data->kind];
3307 data->bank = 0xff; /* Force initial bank selection */
3308 platform_set_drvdata(pdev, data);
3309
3310 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003311 case nct6106:
3312 data->in_num = 9;
3313 data->pwm_num = 3;
3314 data->auto_pwm_num = 4;
3315 data->temp_fixed_num = 3;
3316 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003317 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003318
3319 data->fan_from_reg = fan_from_reg13;
3320 data->fan_from_reg_min = fan_from_reg13;
3321
3322 data->temp_label = nct6776_temp_label;
3323 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3324
3325 data->REG_VBAT = NCT6106_REG_VBAT;
3326 data->REG_DIODE = NCT6106_REG_DIODE;
3327 data->DIODE_MASK = NCT6106_DIODE_MASK;
3328 data->REG_VIN = NCT6106_REG_IN;
3329 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3330 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3331 data->REG_TARGET = NCT6106_REG_TARGET;
3332 data->REG_FAN = NCT6106_REG_FAN;
3333 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3334 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3335 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3336 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3337 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3338 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3339 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3340 data->REG_PWM[0] = NCT6106_REG_PWM;
3341 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3342 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3343 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3344 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3345 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3346 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3347 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3348 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3349 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3350 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3351 data->REG_CRITICAL_TEMP_TOLERANCE
3352 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3353 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3354 data->CRITICAL_PWM_ENABLE_MASK
3355 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3356 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3357 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3358 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3359 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3360 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3361 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3362 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3363 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3364 data->REG_ALARM = NCT6106_REG_ALARM;
3365 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003366 data->REG_BEEP = NCT6106_REG_BEEP;
3367 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003368
3369 reg_temp = NCT6106_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003370 reg_temp_mon = NCT6106_REG_TEMP_MON;
Guenter Roeck6c009502012-07-01 08:23:15 -07003371 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003372 num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
Guenter Roeck6c009502012-07-01 08:23:15 -07003373 reg_temp_over = NCT6106_REG_TEMP_OVER;
3374 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3375 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3376 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3377 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003378 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3379 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003380
3381 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003382 case nct6775:
3383 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003384 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003385 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003386 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003387 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003388 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003389 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003390
3391 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003392 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003393
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003394 data->fan_from_reg = fan_from_reg16;
3395 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003396 data->target_temp_mask = 0x7f;
3397 data->tolerance_mask = 0x0f;
3398 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003399
Guenter Roeckaa136e52012-12-04 03:26:05 -08003400 data->temp_label = nct6775_temp_label;
3401 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3402
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003403 data->REG_CONFIG = NCT6775_REG_CONFIG;
3404 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003405 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003406 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003407 data->REG_VIN = NCT6775_REG_IN;
3408 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3409 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003410 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003411 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003412 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003413 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003414 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003415 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003416 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3417 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3418 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003419 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003420 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3421 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3422 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3423 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003424 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003425 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3426 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3427 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003428 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3429 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3430 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3431 data->REG_CRITICAL_TEMP_TOLERANCE
3432 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003433 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3434 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003435 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003436 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3437 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3438 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3439 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003440 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003441 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003442
3443 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003444 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003445 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003446 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003447 reg_temp_over = NCT6775_REG_TEMP_OVER;
3448 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3449 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3450 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3451 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3452
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003453 break;
3454 case nct6776:
3455 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003456 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003457 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003458 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003459 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003460 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003461 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003462
3463 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003464 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003465
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003466 data->fan_from_reg = fan_from_reg13;
3467 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003468 data->target_temp_mask = 0xff;
3469 data->tolerance_mask = 0x07;
3470 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003471
Guenter Roeckaa136e52012-12-04 03:26:05 -08003472 data->temp_label = nct6776_temp_label;
3473 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3474
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003475 data->REG_CONFIG = NCT6775_REG_CONFIG;
3476 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003477 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003478 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003479 data->REG_VIN = NCT6775_REG_IN;
3480 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3481 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003482 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003483 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003484 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003485 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003486 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003487 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003488 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3489 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3490 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3491 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003492 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003493 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3494 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003495 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3496 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003497 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3498 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3499 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003500 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3501 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3502 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3503 data->REG_CRITICAL_TEMP_TOLERANCE
3504 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003505 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3506 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003507 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003508 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3509 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3510 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3511 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003512 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003513 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003514
3515 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003516 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003517 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003518 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003519 reg_temp_over = NCT6775_REG_TEMP_OVER;
3520 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3521 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3522 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3523 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3524
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003525 break;
3526 case nct6779:
3527 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003528 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003529 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003530 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003531 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003532 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003533 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003534
3535 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003536 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003537
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003538 data->fan_from_reg = fan_from_reg13;
3539 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003540 data->target_temp_mask = 0xff;
3541 data->tolerance_mask = 0x07;
3542 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003543
Guenter Roeckaa136e52012-12-04 03:26:05 -08003544 data->temp_label = nct6779_temp_label;
3545 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3546
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003547 data->REG_CONFIG = NCT6775_REG_CONFIG;
3548 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003549 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003550 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003551 data->REG_VIN = NCT6779_REG_IN;
3552 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3553 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003554 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003555 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003556 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003557 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003558 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003559 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003560 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3561 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3562 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3563 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003564 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003565 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3566 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003567 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3568 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003569 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3570 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3571 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003572 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3573 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3574 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3575 data->REG_CRITICAL_TEMP_TOLERANCE
3576 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003577 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3578 data->CRITICAL_PWM_ENABLE_MASK
3579 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3580 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003581 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3582 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003583 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003584 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3585 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3586 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3587 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003588 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003589 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003590
3591 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003592 reg_temp_mon = NCT6779_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003593 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003594 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003595 reg_temp_over = NCT6779_REG_TEMP_OVER;
3596 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3597 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3598 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3599 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3600
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003601 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003602 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003603 case nct6792:
David Bartley578ab5f2013-06-24 22:28:28 -07003604 data->in_num = 15;
3605 data->pwm_num = 6;
3606 data->auto_pwm_num = 4;
3607 data->has_fan_div = false;
3608 data->temp_fixed_num = 6;
3609 data->num_temp_alarms = 2;
3610 data->num_temp_beeps = 2;
3611
3612 data->ALARM_BITS = NCT6791_ALARM_BITS;
3613 data->BEEP_BITS = NCT6779_BEEP_BITS;
3614
3615 data->fan_from_reg = fan_from_reg13;
3616 data->fan_from_reg_min = fan_from_reg13;
3617 data->target_temp_mask = 0xff;
3618 data->tolerance_mask = 0x07;
3619 data->speed_tolerance_limit = 63;
3620
3621 data->temp_label = nct6779_temp_label;
3622 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3623
3624 data->REG_CONFIG = NCT6775_REG_CONFIG;
3625 data->REG_VBAT = NCT6775_REG_VBAT;
3626 data->REG_DIODE = NCT6775_REG_DIODE;
3627 data->DIODE_MASK = NCT6775_DIODE_MASK;
3628 data->REG_VIN = NCT6779_REG_IN;
3629 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3630 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3631 data->REG_TARGET = NCT6775_REG_TARGET;
3632 data->REG_FAN = NCT6779_REG_FAN;
3633 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3634 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3635 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3636 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3637 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3638 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3639 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3640 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3641 data->REG_PWM[0] = NCT6775_REG_PWM;
3642 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3643 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003644 data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
3645 data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003646 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3647 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3648 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3649 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3650 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3651 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3652 data->REG_CRITICAL_TEMP_TOLERANCE
3653 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3654 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3655 data->CRITICAL_PWM_ENABLE_MASK
3656 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3657 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3658 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3659 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3660 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003661 data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
3662 data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
3663 data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
3664 data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003665 data->REG_ALARM = NCT6791_REG_ALARM;
Guenter Roeck8aefb932014-11-16 09:50:04 -08003666 if (data->kind == nct6791)
3667 data->REG_BEEP = NCT6776_REG_BEEP;
3668 else
3669 data->REG_BEEP = NCT6792_REG_BEEP;
David Bartley578ab5f2013-06-24 22:28:28 -07003670
3671 reg_temp = NCT6779_REG_TEMP;
3672 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeck8aefb932014-11-16 09:50:04 -08003673 if (data->kind == nct6791) {
3674 reg_temp_mon = NCT6779_REG_TEMP_MON;
3675 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3676 } else {
3677 reg_temp_mon = NCT6792_REG_TEMP_MON;
3678 num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
3679 }
David Bartley578ab5f2013-06-24 22:28:28 -07003680 reg_temp_over = NCT6779_REG_TEMP_OVER;
3681 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3682 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3683 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3684 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3685
3686 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003687 default:
3688 return -ENODEV;
3689 }
3690 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003691 data->have_temp = 0;
3692
3693 /*
3694 * On some boards, not all available temperature sources are monitored,
3695 * even though some of the monitoring registers are unused.
3696 * Get list of unused monitoring registers, then detect if any fan
3697 * controls are configured to use unmonitored temperature sources.
3698 * If so, assign the unmonitored temperature sources to available
3699 * monitoring registers.
3700 */
3701 mask = 0;
3702 available = 0;
3703 for (i = 0; i < num_reg_temp; i++) {
3704 if (reg_temp[i] == 0)
3705 continue;
3706
3707 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3708 if (!src || (mask & (1 << src)))
3709 available |= 1 << i;
3710
3711 mask |= 1 << src;
3712 }
3713
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003714 /*
3715 * Now find unmonitored temperature registers and enable monitoring
3716 * if additional monitoring registers are available.
3717 */
3718 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3719 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3720
Guenter Roeckaa136e52012-12-04 03:26:05 -08003721 mask = 0;
3722 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3723 for (i = 0; i < num_reg_temp; i++) {
3724 if (reg_temp[i] == 0)
3725 continue;
3726
3727 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3728 if (!src || (mask & (1 << src)))
3729 continue;
3730
3731 if (src >= data->temp_label_num ||
3732 !strlen(data->temp_label[src])) {
3733 dev_info(dev,
3734 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3735 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3736 continue;
3737 }
3738
3739 mask |= 1 << src;
3740
3741 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3742 if (src <= data->temp_fixed_num) {
3743 data->have_temp |= 1 << (src - 1);
3744 data->have_temp_fixed |= 1 << (src - 1);
3745 data->reg_temp[0][src - 1] = reg_temp[i];
3746 data->reg_temp[1][src - 1] = reg_temp_over[i];
3747 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003748 if (reg_temp_crit_h && reg_temp_crit_h[i])
3749 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3750 else if (reg_temp_crit[src - 1])
3751 data->reg_temp[3][src - 1]
3752 = reg_temp_crit[src - 1];
3753 if (reg_temp_crit_l && reg_temp_crit_l[i])
3754 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003755 data->reg_temp_config[src - 1] = reg_temp_config[i];
3756 data->temp_src[src - 1] = src;
3757 continue;
3758 }
3759
3760 if (s >= NUM_TEMP)
3761 continue;
3762
3763 /* Use dynamic index for other sources */
3764 data->have_temp |= 1 << s;
3765 data->reg_temp[0][s] = reg_temp[i];
3766 data->reg_temp[1][s] = reg_temp_over[i];
3767 data->reg_temp[2][s] = reg_temp_hyst[i];
3768 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003769 if (reg_temp_crit_h && reg_temp_crit_h[i])
3770 data->reg_temp[3][s] = reg_temp_crit_h[i];
3771 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003772 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003773 if (reg_temp_crit_l && reg_temp_crit_l[i])
3774 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003775
3776 data->temp_src[s] = src;
3777 s++;
3778 }
3779
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003780 /*
3781 * Repeat with temperatures used for fan control.
3782 * This set of registers does not support limits.
3783 */
3784 for (i = 0; i < num_reg_temp_mon; i++) {
3785 if (reg_temp_mon[i] == 0)
3786 continue;
3787
3788 src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
3789 if (!src || (mask & (1 << src)))
3790 continue;
3791
3792 if (src >= data->temp_label_num ||
3793 !strlen(data->temp_label[src])) {
3794 dev_info(dev,
3795 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3796 src, i, data->REG_TEMP_SEL[i],
3797 reg_temp_mon[i]);
3798 continue;
3799 }
3800
3801 mask |= 1 << src;
3802
3803 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3804 if (src <= data->temp_fixed_num) {
3805 if (data->have_temp & (1 << (src - 1)))
3806 continue;
3807 data->have_temp |= 1 << (src - 1);
3808 data->have_temp_fixed |= 1 << (src - 1);
3809 data->reg_temp[0][src - 1] = reg_temp_mon[i];
3810 data->temp_src[src - 1] = src;
3811 continue;
3812 }
3813
3814 if (s >= NUM_TEMP)
3815 continue;
3816
3817 /* Use dynamic index for other sources */
3818 data->have_temp |= 1 << s;
3819 data->reg_temp[0][s] = reg_temp_mon[i];
3820 data->temp_src[s] = src;
3821 s++;
3822 }
3823
Guenter Roeckaa136e52012-12-04 03:26:05 -08003824#ifdef USE_ALTERNATE
3825 /*
3826 * Go through the list of alternate temp registers and enable
3827 * if possible.
3828 * The temperature is already monitored if the respective bit in <mask>
3829 * is set.
3830 */
3831 for (i = 0; i < data->temp_label_num - 1; i++) {
3832 if (!reg_temp_alternate[i])
3833 continue;
3834 if (mask & (1 << (i + 1)))
3835 continue;
3836 if (i < data->temp_fixed_num) {
3837 if (data->have_temp & (1 << i))
3838 continue;
3839 data->have_temp |= 1 << i;
3840 data->have_temp_fixed |= 1 << i;
3841 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003842 if (i < num_reg_temp) {
3843 data->reg_temp[1][i] = reg_temp_over[i];
3844 data->reg_temp[2][i] = reg_temp_hyst[i];
3845 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003846 data->temp_src[i] = i + 1;
3847 continue;
3848 }
3849
3850 if (s >= NUM_TEMP) /* Abort if no more space */
3851 break;
3852
3853 data->have_temp |= 1 << s;
3854 data->reg_temp[0][s] = reg_temp_alternate[i];
3855 data->temp_src[s] = i + 1;
3856 s++;
3857 }
3858#endif /* USE_ALTERNATE */
3859
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003860 /* Initialize the chip */
3861 nct6775_init_device(data);
3862
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003863 err = superio_enter(sio_data->sioreg);
3864 if (err)
3865 return err;
3866
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003867 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3868 switch (data->kind) {
3869 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003870 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003871 break;
3872 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003873 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003874 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003875 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003876 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003877 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003878 case nct6792:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003879 break;
3880 }
3881
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003882 /*
3883 * Read VID value
3884 * We can get the VID input values directly at logical device D 0xe3.
3885 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003886 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003887 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3888 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3889 data->vrm = vid_which_vrm();
3890 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003891
3892 if (fan_debounce) {
3893 u8 tmp;
3894
3895 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3896 tmp = superio_inb(sio_data->sioreg,
3897 NCT6775_REG_CR_FAN_DEBOUNCE);
3898 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003899 case nct6106:
3900 tmp |= 0xe0;
3901 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003902 case nct6775:
3903 tmp |= 0x1e;
3904 break;
3905 case nct6776:
3906 case nct6779:
3907 tmp |= 0x3e;
3908 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003909 case nct6791:
Guenter Roeck8aefb932014-11-16 09:50:04 -08003910 case nct6792:
David Bartley578ab5f2013-06-24 22:28:28 -07003911 tmp |= 0x7e;
3912 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003913 }
3914 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3915 tmp);
3916 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3917 data->name);
3918 }
3919
Guenter Roeckdf612d52013-07-08 13:15:04 -07003920 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003921
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003922 superio_exit(sio_data->sioreg);
3923
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003924 /* Read fan clock dividers immediately */
3925 nct6775_init_fan_common(dev, data);
3926
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003927 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003928 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3929 data->pwm_num);
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003930 if (IS_ERR(group))
3931 return PTR_ERR(group);
3932
Axel Lin55bdee62014-07-24 08:59:34 +08003933 data->groups[num_attr_groups++] = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003934
Guenter Roeckf73cf632013-03-18 09:22:50 -07003935 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3936 fls(data->have_in));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003937 if (IS_ERR(group))
3938 return PTR_ERR(group);
3939
Axel Lin55bdee62014-07-24 08:59:34 +08003940 data->groups[num_attr_groups++] = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003941
Guenter Roeckf73cf632013-03-18 09:22:50 -07003942 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3943 fls(data->has_fan));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003944 if (IS_ERR(group))
3945 return PTR_ERR(group);
3946
Axel Lin55bdee62014-07-24 08:59:34 +08003947 data->groups[num_attr_groups++] = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003948
Guenter Roeckf73cf632013-03-18 09:22:50 -07003949 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3950 fls(data->have_temp));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003951 if (IS_ERR(group))
3952 return PTR_ERR(group);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003953
Axel Lin55bdee62014-07-24 08:59:34 +08003954 data->groups[num_attr_groups++] = group;
3955 data->groups[num_attr_groups++] = &nct6775_group_other;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003956
Guenter Roecka150d952013-07-11 22:55:22 -07003957 hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
3958 data, data->groups);
Fengguang Wu9c09bd82013-09-17 06:43:42 -07003959 return PTR_ERR_OR_ZERO(hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003960}
3961
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003962static void nct6791_enable_io_mapping(int sioaddr)
3963{
3964 int val;
3965
3966 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
3967 if (val & 0x10) {
3968 pr_info("Enabling hardware monitor logical device mappings.\n");
3969 superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
3970 val & ~0x10);
3971 }
3972}
3973
Guenter Roeck84d19d92012-12-04 08:01:39 -08003974#ifdef CONFIG_PM
3975static int nct6775_suspend(struct device *dev)
3976{
3977 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003978
3979 mutex_lock(&data->update_lock);
3980 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003981 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003982 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3983 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3984 }
3985 mutex_unlock(&data->update_lock);
3986
3987 return 0;
3988}
3989
3990static int nct6775_resume(struct device *dev)
3991{
3992 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003993 int i, j, err = 0;
Guenter Roeck84d19d92012-12-04 08:01:39 -08003994
3995 mutex_lock(&data->update_lock);
3996 data->bank = 0xff; /* Force initial bank selection */
3997
Guenter Roeck8aefb932014-11-16 09:50:04 -08003998 if (data->kind == nct6791 || data->kind == nct6792) {
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003999 err = superio_enter(data->sioreg);
4000 if (err)
4001 goto abort;
4002
4003 nct6791_enable_io_mapping(data->sioreg);
4004 superio_exit(data->sioreg);
4005 }
4006
Guenter Roeck84d19d92012-12-04 08:01:39 -08004007 /* Restore limits */
4008 for (i = 0; i < data->in_num; i++) {
4009 if (!(data->have_in & (1 << i)))
4010 continue;
4011
4012 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
4013 data->in[i][1]);
4014 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
4015 data->in[i][2]);
4016 }
4017
Guenter Roeckc409fd42013-04-09 05:04:00 -07004018 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004019 if (!(data->has_fan_min & (1 << i)))
4020 continue;
4021
4022 nct6775_write_value(data, data->REG_FAN_MIN[i],
4023 data->fan_min[i]);
4024 }
4025
4026 for (i = 0; i < NUM_TEMP; i++) {
4027 if (!(data->have_temp & (1 << i)))
4028 continue;
4029
Guenter Roeckc409fd42013-04-09 05:04:00 -07004030 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08004031 if (data->reg_temp[j][i])
4032 nct6775_write_temp(data, data->reg_temp[j][i],
4033 data->temp[j][i]);
4034 }
4035
4036 /* Restore other settings */
4037 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07004038 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004039 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
4040 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
4041 }
4042
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004043abort:
Guenter Roeck84d19d92012-12-04 08:01:39 -08004044 /* Force re-reading all values */
4045 data->valid = false;
4046 mutex_unlock(&data->update_lock);
4047
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004048 return err;
Guenter Roeck84d19d92012-12-04 08:01:39 -08004049}
4050
4051static const struct dev_pm_ops nct6775_dev_pm_ops = {
4052 .suspend = nct6775_suspend,
4053 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02004054 .freeze = nct6775_suspend,
4055 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004056};
4057
4058#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4059#else
4060#define NCT6775_DEV_PM_OPS NULL
4061#endif /* CONFIG_PM */
4062
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004063static struct platform_driver nct6775_driver = {
4064 .driver = {
4065 .owner = THIS_MODULE,
4066 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004067 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004068 },
4069 .probe = nct6775_probe,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004070};
4071
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004072static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004073 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004074 "NCT6775F",
4075 "NCT6776D/F",
4076 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004077 "NCT6791D",
Guenter Roeck8aefb932014-11-16 09:50:04 -08004078 "NCT6792D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004079};
4080
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004081/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004082static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004083{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004084 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004085 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004086 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004087
4088 err = superio_enter(sioaddr);
4089 if (err)
4090 return err;
4091
4092 if (force_id)
4093 val = force_id;
4094 else
4095 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4096 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4097 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004098 case SIO_NCT6106_ID:
4099 sio_data->kind = nct6106;
4100 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004101 case SIO_NCT6775_ID:
4102 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004103 break;
4104 case SIO_NCT6776_ID:
4105 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004106 break;
4107 case SIO_NCT6779_ID:
4108 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004109 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004110 case SIO_NCT6791_ID:
4111 sio_data->kind = nct6791;
4112 break;
Guenter Roeck8aefb932014-11-16 09:50:04 -08004113 case SIO_NCT6792_ID:
4114 sio_data->kind = nct6792;
4115 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004116 default:
4117 if (val != 0xffff)
4118 pr_debug("unsupported chip ID: 0x%04x\n", val);
4119 superio_exit(sioaddr);
4120 return -ENODEV;
4121 }
4122
4123 /* We have a known chip, find the HWM I/O address */
4124 superio_select(sioaddr, NCT6775_LD_HWM);
4125 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4126 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004127 addr = val & IOREGION_ALIGNMENT;
4128 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004129 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4130 superio_exit(sioaddr);
4131 return -ENODEV;
4132 }
4133
4134 /* Activate logical device if needed */
4135 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4136 if (!(val & 0x01)) {
4137 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4138 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4139 }
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004140
Guenter Roeck8aefb932014-11-16 09:50:04 -08004141 if (sio_data->kind == nct6791 || sio_data->kind == nct6792)
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004142 nct6791_enable_io_mapping(sioaddr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004143
4144 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004145 pr_info("Found %s or compatible chip at %#x:%#x\n",
4146 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004147 sio_data->sioreg = sioaddr;
4148
Guenter Roeck698a7c22013-04-05 07:35:25 -07004149 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004150}
4151
4152/*
4153 * when Super-I/O functions move to a separate file, the Super-I/O
4154 * bus will manage the lifetime of the device and this module will only keep
Guenter Roeck615fc8c2013-07-06 09:43:30 -07004155 * track of the nct6775 driver. But since we use platform_device_alloc(), we
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004156 * must keep track of the device
4157 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004158static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004159
4160static int __init sensors_nct6775_init(void)
4161{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004162 int i, err;
4163 bool found = false;
4164 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004165 struct resource res;
4166 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004167 int sioaddr[2] = { 0x2e, 0x4e };
4168
4169 err = platform_driver_register(&nct6775_driver);
4170 if (err)
4171 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004172
4173 /*
4174 * initialize sio_data->kind and sio_data->sioreg.
4175 *
4176 * when Super-I/O functions move to a separate file, the Super-I/O
4177 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4178 * nct6775 hardware monitor, and call probe()
4179 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004180 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4181 address = nct6775_find(sioaddr[i], &sio_data);
4182 if (address <= 0)
4183 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004184
Guenter Roeck698a7c22013-04-05 07:35:25 -07004185 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004186
Guenter Roeck698a7c22013-04-05 07:35:25 -07004187 pdev[i] = platform_device_alloc(DRVNAME, address);
4188 if (!pdev[i]) {
4189 err = -ENOMEM;
Axel Lin9d311ed2014-05-24 23:21:23 +08004190 goto exit_device_unregister;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004191 }
4192
4193 err = platform_device_add_data(pdev[i], &sio_data,
4194 sizeof(struct nct6775_sio_data));
4195 if (err)
4196 goto exit_device_put;
4197
4198 memset(&res, 0, sizeof(res));
4199 res.name = DRVNAME;
4200 res.start = address + IOREGION_OFFSET;
4201 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4202 res.flags = IORESOURCE_IO;
4203
4204 err = acpi_check_resource_conflict(&res);
4205 if (err) {
4206 platform_device_put(pdev[i]);
4207 pdev[i] = NULL;
4208 continue;
4209 }
4210
4211 err = platform_device_add_resources(pdev[i], &res, 1);
4212 if (err)
4213 goto exit_device_put;
4214
4215 /* platform_device_add calls probe() */
4216 err = platform_device_add(pdev[i]);
4217 if (err)
4218 goto exit_device_put;
4219 }
4220 if (!found) {
4221 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004222 goto exit_unregister;
4223 }
4224
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004225 return 0;
4226
4227exit_device_put:
Axel Lin9d311ed2014-05-24 23:21:23 +08004228 platform_device_put(pdev[i]);
4229exit_device_unregister:
4230 while (--i >= 0) {
Guenter Roeck698a7c22013-04-05 07:35:25 -07004231 if (pdev[i])
Axel Lin9d311ed2014-05-24 23:21:23 +08004232 platform_device_unregister(pdev[i]);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004233 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004234exit_unregister:
4235 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004236 return err;
4237}
4238
4239static void __exit sensors_nct6775_exit(void)
4240{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004241 int i;
4242
4243 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4244 if (pdev[i])
4245 platform_device_unregister(pdev[i]);
4246 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004247 platform_driver_unregister(&nct6775_driver);
4248}
4249
4250MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
Guenter Roeck8aefb932014-11-16 09:50:04 -08004251MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver");
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004252MODULE_LICENSE("GPL");
4253
4254module_init(sensors_nct6775_init);
4255module_exit(sensors_nct6775_exit);