aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim V. Vlasov <vvlasov@dev.rtsoft.ru>2015-02-27 08:16:00 -0500
committerGuenter Roeck <linux@roeck-us.net>2015-03-09 12:59:36 -0400
commit9c947d25c96ec93485d60f7b783403d518c1418d (patch)
tree8d87bbe5f0d1a327f23f37b5e08316d50360a8ff
parente8433b42b60e799d55eb2476dc6cb3668c740063 (diff)
hwmon: Add Nuvoton NCT7904 hwmon driver
The NCT7904D is a hardware monitor supporting up to 20 voltage sensors, internal temperature sensor, Intel PECI and AMD SB-TSI CPU temperature interface, up to 12 fan tachometer inputs, up to 4 fan control channels with SmartFan. Signed-off-by: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru> [Guenter Roeck: Fixed whitespace errors, dropped redundant comment] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/nct790460
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/nct7904.c592
4 files changed, 663 insertions, 0 deletions
diff --git a/Documentation/hwmon/nct7904 b/Documentation/hwmon/nct7904
new file mode 100644
index 000000000000..014f112e2a14
--- /dev/null
+++ b/Documentation/hwmon/nct7904
@@ -0,0 +1,60 @@
1Kernel driver nct7904
2====================
3
4Supported chip:
5 * Nuvoton NCT7904D
6 Prefix: nct7904
7 Addresses: I2C 0x2d, 0x2e
8 Datasheet: Publicly available at Nuvoton website
9 http://www.nuvoton.com/
10
11Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
12
13
14Description
15-----------
16
17The NCT7904D is a hardware monitor supporting up to 20 voltage sensors,
18internal temperature sensor, Intel PECI and AMD SB-TSI CPU temperature
19interface, up to 12 fan tachometer inputs, up to 4 fan control channels
20with SmartFan.
21
22
23Sysfs entries
24-------------
25
26Currently, the driver supports only the following features:
27
28in[1-20]_input Input voltage measurements (mV)
29
30fan[1-12]_input Fan tachometer measurements (rpm)
31
32temp1_input Local temperature (1/1000 degree,
33 0.125 degree resolution)
34
35temp[2-9]_input CPU temperatures (1/1000 degree,
36 0.125 degree resolution)
37
38fan[1-4]_mode R/W, 0/1 for manual or SmartFan mode
39 Setting SmartFan mode is supported only if it has been
40 previously configured by BIOS (or configuration EEPROM)
41
42fan[1-4]_pwm R/O in SmartFan mode, R/W in manual control mode
43
44The driver checks sensor control registers and does not export the sensors
45that are not enabled. Anyway, a sensor that is enabled may actually be not
46connected and thus provide zero readings.
47
48
49Limitations
50-----------
51
52The following features are not supported in current version:
53
54 - SmartFan control
55 - Watchdog
56 - GPIO
57 - external temperature sensors
58 - SMI
59 - min/max values
60 - many other...
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4b40ea79b20f..2a5dd697c142 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1145,6 +1145,16 @@ config SENSORS_NCT7802
1145 This driver can also be built as a module. If so, the module 1145 This driver can also be built as a module. If so, the module
1146 will be called nct7802. 1146 will be called nct7802.
1147 1147
1148config SENSORS_NCT7904
1149 tristate "Nuvoton NCT7904"
1150 depends on I2C
1151 help
1152 If you say yes here you get support for the Nuvoton NCT7904
1153 hardware monitoring chip, including manual fan speed control.
1154
1155 This driver can also be built as a module. If so, the module
1156 will be called nct7904.
1157
1148config SENSORS_PCF8591 1158config SENSORS_PCF8591
1149 tristate "Philips PCF8591 ADC/DAC" 1159 tristate "Philips PCF8591 ADC/DAC"
1150 depends on I2C 1160 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 6c941472e707..b4a40f17e2aa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -120,6 +120,7 @@ obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
120obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o 120obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o
121obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o 121obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
122obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o 122obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o
123obj-$(CONFIG_SENSORS_NCT7904) += nct7904.o
123obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o 124obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
124obj-$(CONFIG_SENSORS_PC87360) += pc87360.o 125obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
125obj-$(CONFIG_SENSORS_PC87427) += pc87427.o 126obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
new file mode 100644
index 000000000000..eaa8234e21d0
--- /dev/null
+++ b/drivers/hwmon/nct7904.c
@@ -0,0 +1,592 @@
1/*
2 * nct7904.c - driver for Nuvoton NCT7904D.
3 *
4 * Copyright (c) 2015 Kontron
5 * Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/init.h>
21#include <linux/i2c.h>
22#include <linux/mutex.h>
23#include <linux/hwmon.h>
24#include <linux/hwmon-sysfs.h>
25
26#define VENDOR_ID_REG 0x7A /* Any bank */
27#define NUVOTON_ID 0x50
28#define CHIP_ID_REG 0x7B /* Any bank */
29#define NCT7904_ID 0xC5
30#define DEVICE_ID_REG 0x7C /* Any bank */
31
32#define BANK_SEL_REG 0xFF
33#define BANK_0 0x00
34#define BANK_1 0x01
35#define BANK_2 0x02
36#define BANK_3 0x03
37#define BANK_4 0x04
38#define BANK_MAX 0x04
39
40#define FANIN_MAX 12 /* Counted from 1 */
41#define VSEN_MAX 21 /* VSEN1..14, 3VDD, VBAT, V3VSB,
42 LTD (not a voltage), VSEN17..19 */
43#define FANCTL_MAX 4 /* Counted from 1 */
44#define TCPU_MAX 8 /* Counted from 1 */
45#define TEMP_MAX 4 /* Counted from 1 */
46
47#define VT_ADC_CTRL0_REG 0x20 /* Bank 0 */
48#define VT_ADC_CTRL1_REG 0x21 /* Bank 0 */
49#define VT_ADC_CTRL2_REG 0x22 /* Bank 0 */
50#define FANIN_CTRL0_REG 0x24
51#define FANIN_CTRL1_REG 0x25
52#define DTS_T_CTRL0_REG 0x26
53#define DTS_T_CTRL1_REG 0x27
54#define VT_ADC_MD_REG 0x2E
55
56#define VSEN1_HV_REG 0x40 /* Bank 0; 2 regs (HV/LV) per sensor */
57#define TEMP_CH1_HV_REG 0x42 /* Bank 0; same as VSEN2_HV */
58#define LTD_HV_REG 0x62 /* Bank 0; 2 regs in VSEN range */
59#define FANIN1_HV_REG 0x80 /* Bank 0; 2 regs (HV/LV) per sensor */
60#define T_CPU1_HV_REG 0xA0 /* Bank 0; 2 regs (HV/LV) per sensor */
61
62#define PRTS_REG 0x03 /* Bank 2 */
63#define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */
64#define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */
65
66static const unsigned short normal_i2c[] = {
67 0x2d, 0x2e, I2C_CLIENT_END
68};
69
70struct nct7904_data {
71 struct i2c_client *client;
72 struct mutex bank_lock;
73 int bank_sel;
74 u32 fanin_mask;
75 u32 vsen_mask;
76 u32 tcpu_mask;
77 u8 fan_mode[FANCTL_MAX];
78};
79
80/* Access functions */
81static int nct7904_bank_lock(struct nct7904_data *data, unsigned bank)
82{
83 int ret;
84
85 mutex_lock(&data->bank_lock);
86 if (data->bank_sel == bank)
87 return 0;
88 ret = i2c_smbus_write_byte_data(data->client, BANK_SEL_REG, bank);
89 if (ret == 0)
90 data->bank_sel = bank;
91 else
92 data->bank_sel = -1;
93 return ret;
94}
95
96static inline void nct7904_bank_release(struct nct7904_data *data)
97{
98 mutex_unlock(&data->bank_lock);
99}
100
101/* Read 1-byte register. Returns unsigned reg or -ERRNO on error. */
102static int nct7904_read_reg(struct nct7904_data *data,
103 unsigned bank, unsigned reg)
104{
105 struct i2c_client *client = data->client;
106 int ret;
107
108 ret = nct7904_bank_lock(data, bank);
109 if (ret == 0)
110 ret = i2c_smbus_read_byte_data(client, reg);
111
112 nct7904_bank_release(data);
113 return ret;
114}
115
116/*
117 * Read 2-byte register. Returns register in big-endian format or
118 * -ERRNO on error.
119 */
120static int nct7904_read_reg16(struct nct7904_data *data,
121 unsigned bank, unsigned reg)
122{
123 struct i2c_client *client = data->client;
124 int ret, hi;
125
126 ret = nct7904_bank_lock(data, bank);
127 if (ret == 0) {
128 ret = i2c_smbus_read_byte_data(client, reg);
129 if (ret >= 0) {
130 hi = ret;
131 ret = i2c_smbus_read_byte_data(client, reg + 1);
132 if (ret >= 0)
133 ret |= hi << 8;
134 }
135 }
136
137 nct7904_bank_release(data);
138 return ret;
139}
140
141/* Write 1-byte register. Returns 0 or -ERRNO on error. */
142static int nct7904_write_reg(struct nct7904_data *data,
143 unsigned bank, unsigned reg, u8 val)
144{
145 struct i2c_client *client = data->client;
146 int ret;
147
148 ret = nct7904_bank_lock(data, bank);
149 if (ret == 0)
150 ret = i2c_smbus_write_byte_data(client, reg, val);
151
152 nct7904_bank_release(data);
153 return ret;
154}
155
156/* FANIN ATTR */
157static ssize_t show_fan(struct device *dev,
158 struct device_attribute *devattr, char *buf)
159{
160 int index = to_sensor_dev_attr(devattr)->index;
161 struct nct7904_data *data = dev_get_drvdata(dev);
162 int ret;
163 unsigned cnt, rpm;
164
165 ret = nct7904_read_reg16(data, BANK_0, FANIN1_HV_REG + index * 2);
166 if (ret < 0)
167 return ret;
168 cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
169 if (cnt == 0x1fff)
170 rpm = 0;
171 else
172 rpm = 1350000 / cnt;
173 return sprintf(buf, "%u\n", rpm);
174}
175
176static umode_t nct7904_fanin_is_visible(struct kobject *kobj,
177 struct attribute *a, int n)
178{
179 struct device *dev = container_of(kobj, struct device, kobj);
180 struct nct7904_data *data = dev_get_drvdata(dev);
181
182 if (data->fanin_mask & (1 << n))
183 return a->mode;
184 return 0;
185}
186
187static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
188static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
189static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
190static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
191static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4);
192static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5);
193static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6);
194static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7);
195static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_fan, NULL, 8);
196static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_fan, NULL, 9);
197static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_fan, NULL, 10);
198static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_fan, NULL, 11);
199
200static struct attribute *nct7904_fanin_attrs[] = {
201 &sensor_dev_attr_fan1_input.dev_attr.attr,
202 &sensor_dev_attr_fan2_input.dev_attr.attr,
203 &sensor_dev_attr_fan3_input.dev_attr.attr,
204 &sensor_dev_attr_fan4_input.dev_attr.attr,
205 &sensor_dev_attr_fan5_input.dev_attr.attr,
206 &sensor_dev_attr_fan6_input.dev_attr.attr,
207 &sensor_dev_attr_fan7_input.dev_attr.attr,
208 &sensor_dev_attr_fan8_input.dev_attr.attr,
209 &sensor_dev_attr_fan9_input.dev_attr.attr,
210 &sensor_dev_attr_fan10_input.dev_attr.attr,
211 &sensor_dev_attr_fan11_input.dev_attr.attr,
212 &sensor_dev_attr_fan12_input.dev_attr.attr,
213 NULL
214};
215
216static const struct attribute_group nct7904_fanin_group = {
217 .attrs = nct7904_fanin_attrs,
218 .is_visible = nct7904_fanin_is_visible,
219};
220
221/* VSEN ATTR */
222static ssize_t show_voltage(struct device *dev,
223 struct device_attribute *devattr, char *buf)
224{
225 int index = to_sensor_dev_attr(devattr)->index;
226 struct nct7904_data *data = dev_get_drvdata(dev);
227 int ret;
228 int volt;
229
230 ret = nct7904_read_reg16(data, BANK_0, VSEN1_HV_REG + index * 2);
231 if (ret < 0)
232 return ret;
233 volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
234 if (index < 14)
235 volt *= 2; /* 0.002V scale */
236 else
237 volt *= 6; /* 0.006V scale */
238
239 return sprintf(buf, "%d\n", volt);
240}
241
242static ssize_t show_ltemp(struct device *dev,
243 struct device_attribute *devattr, char *buf)
244{
245 struct nct7904_data *data = dev_get_drvdata(dev);
246 int ret;
247 int temp;
248
249 ret = nct7904_read_reg16(data, BANK_0, LTD_HV_REG);
250 if (ret < 0)
251 return ret;
252 temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
253 temp = sign_extend32(temp, 10) * 125;
254
255 return sprintf(buf, "%d\n", temp);
256}
257
258static umode_t nct7904_vsen_is_visible(struct kobject *kobj,
259 struct attribute *a, int n)
260{
261 struct device *dev = container_of(kobj, struct device, kobj);
262 struct nct7904_data *data = dev_get_drvdata(dev);
263
264 if (data->vsen_mask & (1 << n))
265 return a->mode;
266 return 0;
267}
268
269static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0);
270static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1);
271static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2);
272static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3);
273static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4);
274static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5);
275static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6);
276static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7);
277static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8);
278static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9);
279static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10);
280static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11);
281static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12);
282static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_voltage, NULL, 13);
283/*
284 * Next 3 voltage sensors have specific names in the Nuvoton doc
285 * (3VDD, VBAT, 3VSB) but we use vacant numbers for them.
286 */
287static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_voltage, NULL, 14);
288static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_voltage, NULL, 15);
289static SENSOR_DEVICE_ATTR(in20_input, S_IRUGO, show_voltage, NULL, 16);
290/* This is not a voltage, but a local temperature sensor. */
291static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_ltemp, NULL, 0);
292static SENSOR_DEVICE_ATTR(in17_input, S_IRUGO, show_voltage, NULL, 18);
293static SENSOR_DEVICE_ATTR(in18_input, S_IRUGO, show_voltage, NULL, 19);
294static SENSOR_DEVICE_ATTR(in19_input, S_IRUGO, show_voltage, NULL, 20);
295
296static struct attribute *nct7904_vsen_attrs[] = {
297 &sensor_dev_attr_in1_input.dev_attr.attr,
298 &sensor_dev_attr_in2_input.dev_attr.attr,
299 &sensor_dev_attr_in3_input.dev_attr.attr,
300 &sensor_dev_attr_in4_input.dev_attr.attr,
301 &sensor_dev_attr_in5_input.dev_attr.attr,
302 &sensor_dev_attr_in6_input.dev_attr.attr,
303 &sensor_dev_attr_in7_input.dev_attr.attr,
304 &sensor_dev_attr_in8_input.dev_attr.attr,
305 &sensor_dev_attr_in9_input.dev_attr.attr,
306 &sensor_dev_attr_in10_input.dev_attr.attr,
307 &sensor_dev_attr_in11_input.dev_attr.attr,
308 &sensor_dev_attr_in12_input.dev_attr.attr,
309 &sensor_dev_attr_in13_input.dev_attr.attr,
310 &sensor_dev_attr_in14_input.dev_attr.attr,
311 &sensor_dev_attr_in15_input.dev_attr.attr,
312 &sensor_dev_attr_in16_input.dev_attr.attr,
313 &sensor_dev_attr_in20_input.dev_attr.attr,
314 &sensor_dev_attr_temp1_input.dev_attr.attr,
315 &sensor_dev_attr_in17_input.dev_attr.attr,
316 &sensor_dev_attr_in18_input.dev_attr.attr,
317 &sensor_dev_attr_in19_input.dev_attr.attr,
318 NULL
319};
320
321static const struct attribute_group nct7904_vsen_group = {
322 .attrs = nct7904_vsen_attrs,
323 .is_visible = nct7904_vsen_is_visible,
324};
325
326/* CPU_TEMP ATTR */
327static ssize_t show_tcpu(struct device *dev,
328 struct device_attribute *devattr, char *buf)
329{
330 int index = to_sensor_dev_attr(devattr)->index;
331 struct nct7904_data *data = dev_get_drvdata(dev);
332 int ret;
333 int temp;
334
335 ret = nct7904_read_reg16(data, BANK_0, T_CPU1_HV_REG + index * 2);
336 if (ret < 0)
337 return ret;
338
339 temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
340 temp = sign_extend32(temp, 10) * 125;
341 return sprintf(buf, "%d\n", temp);
342}
343
344static umode_t nct7904_tcpu_is_visible(struct kobject *kobj,
345 struct attribute *a, int n)
346{
347 struct device *dev = container_of(kobj, struct device, kobj);
348 struct nct7904_data *data = dev_get_drvdata(dev);
349
350 if (data->tcpu_mask & (1 << n))
351 return a->mode;
352 return 0;
353}
354
355/* "temp1_input" reserved for local temp */
356static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_tcpu, NULL, 0);
357static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_tcpu, NULL, 1);
358static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_tcpu, NULL, 2);
359static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_tcpu, NULL, 3);
360static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_tcpu, NULL, 4);
361static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_tcpu, NULL, 5);
362static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_tcpu, NULL, 6);
363static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_tcpu, NULL, 7);
364
365static struct attribute *nct7904_tcpu_attrs[] = {
366 &sensor_dev_attr_temp2_input.dev_attr.attr,
367 &sensor_dev_attr_temp3_input.dev_attr.attr,
368 &sensor_dev_attr_temp4_input.dev_attr.attr,
369 &sensor_dev_attr_temp5_input.dev_attr.attr,
370 &sensor_dev_attr_temp6_input.dev_attr.attr,
371 &sensor_dev_attr_temp7_input.dev_attr.attr,
372 &sensor_dev_attr_temp8_input.dev_attr.attr,
373 &sensor_dev_attr_temp9_input.dev_attr.attr,
374 NULL
375};
376
377static const struct attribute_group nct7904_tcpu_group = {
378 .attrs = nct7904_tcpu_attrs,
379 .is_visible = nct7904_tcpu_is_visible,
380};
381
382/* PWM ATTR */
383static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
384 const char *buf, size_t count)
385{
386 int index = to_sensor_dev_attr(devattr)->index;
387 struct nct7904_data *data = dev_get_drvdata(dev);
388 unsigned long val;
389 int ret;
390
391 if (kstrtoul(buf, 10, &val) < 0)
392 return -EINVAL;
393 if (val > 255)
394 return -EINVAL;
395
396 ret = nct7904_write_reg(data, BANK_3, FANCTL1_OUT_REG + index, val);
397
398 return ret ? ret : count;
399}
400
401static ssize_t show_pwm(struct device *dev,
402 struct device_attribute *devattr, char *buf)
403{
404 int index = to_sensor_dev_attr(devattr)->index;
405 struct nct7904_data *data = dev_get_drvdata(dev);
406 int val;
407
408 val = nct7904_read_reg(data, BANK_3, FANCTL1_OUT_REG + index);
409 if (val < 0)
410 return val;
411
412 return sprintf(buf, "%d\n", val);
413}
414
415static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
416 const char *buf, size_t count)
417{
418 int index = to_sensor_dev_attr(devattr)->index;
419 struct nct7904_data *data = dev_get_drvdata(dev);
420 unsigned long val;
421 int ret;
422
423 if (kstrtoul(buf, 10, &val) < 0)
424 return -EINVAL;
425 if (val > 1 || (val && !data->fan_mode[index]))
426 return -EINVAL;
427
428 ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + index,
429 val ? data->fan_mode[index] : 0);
430
431 return ret ? ret : count;
432}
433
434/* Return 0 for manual mode or 1 for SmartFan mode */
435static ssize_t show_mode(struct device *dev,
436 struct device_attribute *devattr, char *buf)
437{
438 int index = to_sensor_dev_attr(devattr)->index;
439 struct nct7904_data *data = dev_get_drvdata(dev);
440 int val;
441
442 val = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + index);
443 if (val < 0)
444 return val;
445
446 return sprintf(buf, "%d\n", val ? 1 : 0);
447}
448
449/* 2 attributes per channel: pwm and mode */
450static SENSOR_DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR,
451 show_pwm, store_pwm, 0);
452static SENSOR_DEVICE_ATTR(fan1_mode, S_IRUGO | S_IWUSR,
453 show_mode, store_mode, 0);
454static SENSOR_DEVICE_ATTR(fan2_pwm, S_IRUGO | S_IWUSR,
455 show_pwm, store_pwm, 1);
456static SENSOR_DEVICE_ATTR(fan2_mode, S_IRUGO | S_IWUSR,
457 show_mode, store_mode, 1);
458static SENSOR_DEVICE_ATTR(fan3_pwm, S_IRUGO | S_IWUSR,
459 show_pwm, store_pwm, 2);
460static SENSOR_DEVICE_ATTR(fan3_mode, S_IRUGO | S_IWUSR,
461 show_mode, store_mode, 2);
462static SENSOR_DEVICE_ATTR(fan4_pwm, S_IRUGO | S_IWUSR,
463 show_pwm, store_pwm, 3);
464static SENSOR_DEVICE_ATTR(fan4_mode, S_IRUGO | S_IWUSR,
465 show_mode, store_mode, 3);
466
467static struct attribute *nct7904_fanctl_attrs[] = {
468 &sensor_dev_attr_fan1_pwm.dev_attr.attr,
469 &sensor_dev_attr_fan1_mode.dev_attr.attr,
470 &sensor_dev_attr_fan2_pwm.dev_attr.attr,
471 &sensor_dev_attr_fan2_mode.dev_attr.attr,
472 &sensor_dev_attr_fan3_pwm.dev_attr.attr,
473 &sensor_dev_attr_fan3_mode.dev_attr.attr,
474 &sensor_dev_attr_fan4_pwm.dev_attr.attr,
475 &sensor_dev_attr_fan4_mode.dev_attr.attr,
476 NULL
477};
478
479static const struct attribute_group nct7904_fanctl_group = {
480 .attrs = nct7904_fanctl_attrs,
481};
482
483static const struct attribute_group *nct7904_groups[] = {
484 &nct7904_fanin_group,
485 &nct7904_vsen_group,
486 &nct7904_tcpu_group,
487 &nct7904_fanctl_group,
488 NULL
489};
490
491/* Return 0 if detection is successful, -ENODEV otherwise */
492static int nct7904_detect(struct i2c_client *client,
493 struct i2c_board_info *info)
494{
495 struct i2c_adapter *adapter = client->adapter;
496
497 if (!i2c_check_functionality(adapter,
498 I2C_FUNC_SMBUS_READ_BYTE |
499 I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
500 return -ENODEV;
501
502 /* Determine the chip type. */
503 if (i2c_smbus_read_byte_data(client, VENDOR_ID_REG) != NUVOTON_ID ||
504 i2c_smbus_read_byte_data(client, CHIP_ID_REG) != NCT7904_ID ||
505 (i2c_smbus_read_byte_data(client, DEVICE_ID_REG) & 0xf0) != 0x50)
506 return -ENODEV;
507
508 strlcpy(info->type, "nct7904", I2C_NAME_SIZE);
509
510 return 0;
511}
512
513static int nct7904_probe(struct i2c_client *client,
514 const struct i2c_device_id *id)
515{
516 struct nct7904_data *data;
517 struct device *hwmon_dev;
518 struct device *dev = &client->dev;
519 int ret, i;
520 u32 mask;
521
522 data = devm_kzalloc(dev, sizeof(struct nct7904_data), GFP_KERNEL);
523 if (!data)
524 return -ENOMEM;
525
526 data->client = client;
527 mutex_init(&data->bank_lock);
528 data->bank_sel = -1;
529
530 /* Setup sensor groups. */
531 /* FANIN attributes */
532 ret = nct7904_read_reg16(data, BANK_0, FANIN_CTRL0_REG);
533 if (ret < 0)
534 return ret;
535 data->fanin_mask = (ret >> 8) | ((ret & 0xff) << 8);
536
537 /*
538 * VSEN attributes
539 *
540 * Note: voltage sensors overlap with external temperature
541 * sensors. So, if we ever decide to support the latter
542 * we will have to adjust 'vsen_mask' accordingly.
543 */
544 mask = 0;
545 ret = nct7904_read_reg16(data, BANK_0, VT_ADC_CTRL0_REG);
546 if (ret >= 0)
547 mask = (ret >> 8) | ((ret & 0xff) << 8);
548 ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG);
549 if (ret >= 0)
550 mask |= (ret << 16);
551 data->vsen_mask = mask;
552
553 /* CPU_TEMP attributes */
554 ret = nct7904_read_reg16(data, BANK_0, DTS_T_CTRL0_REG);
555 if (ret < 0)
556 return ret;
557 data->tcpu_mask = ((ret >> 8) & 0xf) | ((ret & 0xf) << 4);
558
559 for (i = 0; i < FANCTL_MAX; i++) {
560 ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + i);
561 if (ret < 0)
562 return ret;
563 data->fan_mode[i] = ret;
564 }
565
566 hwmon_dev =
567 devm_hwmon_device_register_with_groups(dev, client->name, data,
568 nct7904_groups);
569 return PTR_ERR_OR_ZERO(hwmon_dev);
570}
571
572static const struct i2c_device_id nct7904_id[] = {
573 {"nct7904", 0},
574 {}
575};
576
577static struct i2c_driver nct7904_driver = {
578 .class = I2C_CLASS_HWMON,
579 .driver = {
580 .name = "nct7904",
581 },
582 .probe = nct7904_probe,
583 .id_table = nct7904_id,
584 .detect = nct7904_detect,
585 .address_list = normal_i2c,
586};
587
588module_i2c_driver(nct7904_driver);
589
590MODULE_AUTHOR("Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>");
591MODULE_DESCRIPTION("Hwmon driver for NUVOTON NCT7904");
592MODULE_LICENSE("GPL");