forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/drivers/hwmon/nct7904.c
....@@ -1,18 +1,20 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * nct7904.c - driver for Nuvoton NCT7904D.
34 *
45 * Copyright (c) 2015 Kontron
56 * Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
67 *
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.
8
+ * Copyright (c) 2019 Advantech
9
+ * Author: Amy.Shih <amy.shih@advantech.com.tw>
1110 *
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.
11
+ * Copyright (c) 2020 Advantech
12
+ * Author: Yuechao Zhao <yuechao.zhao@advantech.com.cn>
13
+ *
14
+ * Supports the following chips:
15
+ *
16
+ * Chip #vin #fan #pwm #temp #dts chip ID
17
+ * nct7904d 20 12 4 5 8 0xc5
1618 */
1719
1820 #include <linux/module.h>
....@@ -21,6 +23,7 @@
2123 #include <linux/i2c.h>
2224 #include <linux/mutex.h>
2325 #include <linux/hwmon.h>
26
+#include <linux/watchdog.h>
2427
2528 #define VENDOR_ID_REG 0x7A /* Any bank */
2629 #define NUVOTON_ID 0x50
....@@ -42,6 +45,7 @@
4245 #define FANCTL_MAX 4 /* Counted from 1 */
4346 #define TCPU_MAX 8 /* Counted from 1 */
4447 #define TEMP_MAX 4 /* Counted from 1 */
48
+#define SMI_STS_MAX 10 /* Counted from 1 */
4549
4650 #define VT_ADC_CTRL0_REG 0x20 /* Bank 0 */
4751 #define VT_ADC_CTRL1_REG 0x21 /* Bank 0 */
....@@ -52,15 +56,70 @@
5256 #define DTS_T_CTRL1_REG 0x27
5357 #define VT_ADC_MD_REG 0x2E
5458
59
+#define VSEN1_HV_LL_REG 0x02 /* Bank 1; 2 regs (HV/LV) per sensor */
60
+#define VSEN1_LV_LL_REG 0x03 /* Bank 1; 2 regs (HV/LV) per sensor */
61
+#define VSEN1_HV_HL_REG 0x00 /* Bank 1; 2 regs (HV/LV) per sensor */
62
+#define VSEN1_LV_HL_REG 0x01 /* Bank 1; 2 regs (HV/LV) per sensor */
63
+#define SMI_STS1_REG 0xC1 /* Bank 0; SMI Status Register */
64
+#define SMI_STS3_REG 0xC3 /* Bank 0; SMI Status Register */
65
+#define SMI_STS5_REG 0xC5 /* Bank 0; SMI Status Register */
66
+#define SMI_STS7_REG 0xC7 /* Bank 0; SMI Status Register */
67
+#define SMI_STS8_REG 0xC8 /* Bank 0; SMI Status Register */
68
+
5569 #define VSEN1_HV_REG 0x40 /* Bank 0; 2 regs (HV/LV) per sensor */
5670 #define TEMP_CH1_HV_REG 0x42 /* Bank 0; same as VSEN2_HV */
5771 #define LTD_HV_REG 0x62 /* Bank 0; 2 regs in VSEN range */
72
+#define LTD_HV_HL_REG 0x44 /* Bank 1; 1 reg for LTD */
73
+#define LTD_LV_HL_REG 0x45 /* Bank 1; 1 reg for LTD */
74
+#define LTD_HV_LL_REG 0x46 /* Bank 1; 1 reg for LTD */
75
+#define LTD_LV_LL_REG 0x47 /* Bank 1; 1 reg for LTD */
76
+#define TEMP_CH1_CH_REG 0x05 /* Bank 1; 1 reg for LTD */
77
+#define TEMP_CH1_W_REG 0x06 /* Bank 1; 1 reg for LTD */
78
+#define TEMP_CH1_WH_REG 0x07 /* Bank 1; 1 reg for LTD */
79
+#define TEMP_CH1_C_REG 0x04 /* Bank 1; 1 reg per sensor */
80
+#define DTS_T_CPU1_C_REG 0x90 /* Bank 1; 1 reg per sensor */
81
+#define DTS_T_CPU1_CH_REG 0x91 /* Bank 1; 1 reg per sensor */
82
+#define DTS_T_CPU1_W_REG 0x92 /* Bank 1; 1 reg per sensor */
83
+#define DTS_T_CPU1_WH_REG 0x93 /* Bank 1; 1 reg per sensor */
5884 #define FANIN1_HV_REG 0x80 /* Bank 0; 2 regs (HV/LV) per sensor */
85
+#define FANIN1_HV_HL_REG 0x60 /* Bank 1; 2 regs (HV/LV) per sensor */
86
+#define FANIN1_LV_HL_REG 0x61 /* Bank 1; 2 regs (HV/LV) per sensor */
5987 #define T_CPU1_HV_REG 0xA0 /* Bank 0; 2 regs (HV/LV) per sensor */
6088
6189 #define PRTS_REG 0x03 /* Bank 2 */
90
+#define PFE_REG 0x00 /* Bank 2; PECI Function Enable */
91
+#define TSI_CTRL_REG 0x50 /* Bank 2; TSI Control Register */
6292 #define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */
6393 #define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */
94
+
95
+#define WDT_LOCK_REG 0xE0 /* W/O Lock Watchdog Register */
96
+#define WDT_EN_REG 0xE1 /* R/O Watchdog Enable Register */
97
+#define WDT_STS_REG 0xE2 /* R/O Watchdog Status Register */
98
+#define WDT_TIMER_REG 0xE3 /* R/W Watchdog Timer Register */
99
+#define WDT_SOFT_EN 0x55 /* Enable soft watchdog timer */
100
+#define WDT_SOFT_DIS 0xAA /* Disable soft watchdog timer */
101
+
102
+#define VOLT_MONITOR_MODE 0x0
103
+#define THERMAL_DIODE_MODE 0x1
104
+#define THERMISTOR_MODE 0x3
105
+
106
+#define ENABLE_TSI BIT(1)
107
+
108
+#define WATCHDOG_TIMEOUT 1 /* 1 minute default timeout */
109
+
110
+/*The timeout range is 1-255 minutes*/
111
+#define MIN_TIMEOUT (1 * 60)
112
+#define MAX_TIMEOUT (255 * 60)
113
+
114
+static int timeout;
115
+module_param(timeout, int, 0);
116
+MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes. 1 <= timeout <= 255, default="
117
+ __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
118
+
119
+static bool nowayout = WATCHDOG_NOWAYOUT;
120
+module_param(nowayout, bool, 0);
121
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
122
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
64123
65124 static const unsigned short normal_i2c[] = {
66125 0x2d, 0x2e, I2C_CLIENT_END
....@@ -68,12 +127,18 @@
68127
69128 struct nct7904_data {
70129 struct i2c_client *client;
130
+ struct watchdog_device wdt;
71131 struct mutex bank_lock;
72132 int bank_sel;
73133 u32 fanin_mask;
74134 u32 vsen_mask;
75135 u32 tcpu_mask;
76136 u8 fan_mode[FANCTL_MAX];
137
+ u8 enable_dts;
138
+ u8 has_dts;
139
+ u8 temp_mode; /* 0: TR mode, 1: TD mode */
140
+ u8 fan_alarm[2];
141
+ u8 vsen_alarm[3];
77142 };
78143
79144 /* Access functions */
....@@ -166,11 +231,38 @@
166231 if (ret < 0)
167232 return ret;
168233 cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
169
- if (cnt == 0x1fff)
234
+ if (cnt == 0 || cnt == 0x1fff)
170235 rpm = 0;
171236 else
172237 rpm = 1350000 / cnt;
173238 *val = rpm;
239
+ return 0;
240
+ case hwmon_fan_min:
241
+ ret = nct7904_read_reg16(data, BANK_1,
242
+ FANIN1_HV_HL_REG + channel * 2);
243
+ if (ret < 0)
244
+ return ret;
245
+ cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
246
+ if (cnt == 0 || cnt == 0x1fff)
247
+ rpm = 0;
248
+ else
249
+ rpm = 1350000 / cnt;
250
+ *val = rpm;
251
+ return 0;
252
+ case hwmon_fan_alarm:
253
+ ret = nct7904_read_reg(data, BANK_0,
254
+ SMI_STS5_REG + (channel >> 3));
255
+ if (ret < 0)
256
+ return ret;
257
+ if (!data->fan_alarm[channel >> 3])
258
+ data->fan_alarm[channel >> 3] = ret & 0xff;
259
+ else
260
+ /* If there is new alarm showing up */
261
+ data->fan_alarm[channel >> 3] |= (ret & 0xff);
262
+ *val = (data->fan_alarm[channel >> 3] >> (channel & 0x07)) & 1;
263
+ /* Needs to clean the alarm if alarm existing */
264
+ if (*val)
265
+ data->fan_alarm[channel >> 3] ^= 1 << (channel & 0x07);
174266 return 0;
175267 default:
176268 return -EOPNOTSUPP;
....@@ -181,8 +273,20 @@
181273 {
182274 const struct nct7904_data *data = _data;
183275
184
- if (attr == hwmon_fan_input && data->fanin_mask & (1 << channel))
185
- return S_IRUGO;
276
+ switch (attr) {
277
+ case hwmon_fan_input:
278
+ case hwmon_fan_alarm:
279
+ if (data->fanin_mask & (1 << channel))
280
+ return 0444;
281
+ break;
282
+ case hwmon_fan_min:
283
+ if (data->fanin_mask & (1 << channel))
284
+ return 0644;
285
+ break;
286
+ default:
287
+ break;
288
+ }
289
+
186290 return 0;
187291 }
188292
....@@ -213,6 +317,45 @@
213317 volt *= 6; /* 0.006V scale */
214318 *val = volt;
215319 return 0;
320
+ case hwmon_in_min:
321
+ ret = nct7904_read_reg16(data, BANK_1,
322
+ VSEN1_HV_LL_REG + index * 4);
323
+ if (ret < 0)
324
+ return ret;
325
+ volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
326
+ if (index < 14)
327
+ volt *= 2; /* 0.002V scale */
328
+ else
329
+ volt *= 6; /* 0.006V scale */
330
+ *val = volt;
331
+ return 0;
332
+ case hwmon_in_max:
333
+ ret = nct7904_read_reg16(data, BANK_1,
334
+ VSEN1_HV_HL_REG + index * 4);
335
+ if (ret < 0)
336
+ return ret;
337
+ volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
338
+ if (index < 14)
339
+ volt *= 2; /* 0.002V scale */
340
+ else
341
+ volt *= 6; /* 0.006V scale */
342
+ *val = volt;
343
+ return 0;
344
+ case hwmon_in_alarm:
345
+ ret = nct7904_read_reg(data, BANK_0,
346
+ SMI_STS1_REG + (index >> 3));
347
+ if (ret < 0)
348
+ return ret;
349
+ if (!data->vsen_alarm[index >> 3])
350
+ data->vsen_alarm[index >> 3] = ret & 0xff;
351
+ else
352
+ /* If there is new alarm showing up */
353
+ data->vsen_alarm[index >> 3] |= (ret & 0xff);
354
+ *val = (data->vsen_alarm[index >> 3] >> (index & 0x07)) & 1;
355
+ /* Needs to clean the alarm if alarm existing */
356
+ if (*val)
357
+ data->vsen_alarm[index >> 3] ^= 1 << (index & 0x07);
358
+ return 0;
216359 default:
217360 return -EOPNOTSUPP;
218361 }
....@@ -223,9 +366,20 @@
223366 const struct nct7904_data *data = _data;
224367 int index = nct7904_chan_to_index[channel];
225368
226
- if (channel > 0 && attr == hwmon_in_input &&
227
- (data->vsen_mask & BIT(index)))
228
- return S_IRUGO;
369
+ switch (attr) {
370
+ case hwmon_in_input:
371
+ case hwmon_in_alarm:
372
+ if (channel > 0 && (data->vsen_mask & BIT(index)))
373
+ return 0444;
374
+ break;
375
+ case hwmon_in_min:
376
+ case hwmon_in_max:
377
+ if (channel > 0 && (data->vsen_mask & BIT(index)))
378
+ return 0644;
379
+ break;
380
+ default:
381
+ break;
382
+ }
229383
230384 return 0;
231385 }
....@@ -235,36 +389,148 @@
235389 {
236390 struct nct7904_data *data = dev_get_drvdata(dev);
237391 int ret, temp;
392
+ unsigned int reg1, reg2, reg3;
393
+ s8 temps;
238394
239395 switch (attr) {
240396 case hwmon_temp_input:
241
- if (channel == 0)
397
+ if (channel == 4)
242398 ret = nct7904_read_reg16(data, BANK_0, LTD_HV_REG);
399
+ else if (channel < 5)
400
+ ret = nct7904_read_reg16(data, BANK_0,
401
+ TEMP_CH1_HV_REG + channel * 4);
243402 else
244403 ret = nct7904_read_reg16(data, BANK_0,
245
- T_CPU1_HV_REG + (channel - 1) * 2);
404
+ T_CPU1_HV_REG + (channel - 5)
405
+ * 2);
246406 if (ret < 0)
247407 return ret;
248408 temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
249409 *val = sign_extend32(temp, 10) * 125;
250410 return 0;
411
+ case hwmon_temp_alarm:
412
+ if (channel == 4) {
413
+ ret = nct7904_read_reg(data, BANK_0,
414
+ SMI_STS3_REG);
415
+ if (ret < 0)
416
+ return ret;
417
+ *val = (ret >> 1) & 1;
418
+ } else if (channel < 4) {
419
+ ret = nct7904_read_reg(data, BANK_0,
420
+ SMI_STS1_REG);
421
+ if (ret < 0)
422
+ return ret;
423
+ *val = (ret >> (((channel * 2) + 1) & 0x07)) & 1;
424
+ } else {
425
+ if ((channel - 5) < 4) {
426
+ ret = nct7904_read_reg(data, BANK_0,
427
+ SMI_STS7_REG +
428
+ ((channel - 5) >> 3));
429
+ if (ret < 0)
430
+ return ret;
431
+ *val = (ret >> ((channel - 5) & 0x07)) & 1;
432
+ } else {
433
+ ret = nct7904_read_reg(data, BANK_0,
434
+ SMI_STS8_REG +
435
+ ((channel - 5) >> 3));
436
+ if (ret < 0)
437
+ return ret;
438
+ *val = (ret >> (((channel - 5) & 0x07) - 4))
439
+ & 1;
440
+ }
441
+ }
442
+ return 0;
443
+ case hwmon_temp_type:
444
+ if (channel < 5) {
445
+ if ((data->tcpu_mask >> channel) & 0x01) {
446
+ if ((data->temp_mode >> channel) & 0x01)
447
+ *val = 3; /* TD */
448
+ else
449
+ *val = 4; /* TR */
450
+ } else {
451
+ *val = 0;
452
+ }
453
+ } else {
454
+ if ((data->has_dts >> (channel - 5)) & 0x01) {
455
+ if (data->enable_dts & ENABLE_TSI)
456
+ *val = 5; /* TSI */
457
+ else
458
+ *val = 6; /* PECI */
459
+ } else {
460
+ *val = 0;
461
+ }
462
+ }
463
+ return 0;
464
+ case hwmon_temp_max:
465
+ reg1 = LTD_HV_LL_REG;
466
+ reg2 = TEMP_CH1_W_REG;
467
+ reg3 = DTS_T_CPU1_W_REG;
468
+ break;
469
+ case hwmon_temp_max_hyst:
470
+ reg1 = LTD_LV_LL_REG;
471
+ reg2 = TEMP_CH1_WH_REG;
472
+ reg3 = DTS_T_CPU1_WH_REG;
473
+ break;
474
+ case hwmon_temp_crit:
475
+ reg1 = LTD_HV_HL_REG;
476
+ reg2 = TEMP_CH1_C_REG;
477
+ reg3 = DTS_T_CPU1_C_REG;
478
+ break;
479
+ case hwmon_temp_crit_hyst:
480
+ reg1 = LTD_LV_HL_REG;
481
+ reg2 = TEMP_CH1_CH_REG;
482
+ reg3 = DTS_T_CPU1_CH_REG;
483
+ break;
251484 default:
252485 return -EOPNOTSUPP;
253486 }
487
+
488
+ if (channel == 4)
489
+ ret = nct7904_read_reg(data, BANK_1, reg1);
490
+ else if (channel < 5)
491
+ ret = nct7904_read_reg(data, BANK_1,
492
+ reg2 + channel * 8);
493
+ else
494
+ ret = nct7904_read_reg(data, BANK_1,
495
+ reg3 + (channel - 5) * 4);
496
+
497
+ if (ret < 0)
498
+ return ret;
499
+ temps = ret;
500
+ *val = temps * 1000;
501
+ return 0;
254502 }
255503
256504 static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel)
257505 {
258506 const struct nct7904_data *data = _data;
259507
260
- if (attr == hwmon_temp_input) {
261
- if (channel == 0) {
262
- if (data->vsen_mask & BIT(17))
263
- return S_IRUGO;
508
+ switch (attr) {
509
+ case hwmon_temp_input:
510
+ case hwmon_temp_alarm:
511
+ case hwmon_temp_type:
512
+ if (channel < 5) {
513
+ if (data->tcpu_mask & BIT(channel))
514
+ return 0444;
264515 } else {
265
- if (data->tcpu_mask & BIT(channel - 1))
266
- return S_IRUGO;
516
+ if (data->has_dts & BIT(channel - 5))
517
+ return 0444;
267518 }
519
+ break;
520
+ case hwmon_temp_max:
521
+ case hwmon_temp_max_hyst:
522
+ case hwmon_temp_crit:
523
+ case hwmon_temp_crit_hyst:
524
+ if (channel < 5) {
525
+ if (data->tcpu_mask & BIT(channel))
526
+ return 0644;
527
+ } else {
528
+ if (data->has_dts & BIT(channel - 5))
529
+ return 0644;
530
+ }
531
+ break;
532
+ default:
533
+ break;
268534 }
269535
270536 return 0;
....@@ -290,6 +556,137 @@
290556
291557 *val = ret ? 2 : 1;
292558 return 0;
559
+ default:
560
+ return -EOPNOTSUPP;
561
+ }
562
+}
563
+
564
+static int nct7904_write_temp(struct device *dev, u32 attr, int channel,
565
+ long val)
566
+{
567
+ struct nct7904_data *data = dev_get_drvdata(dev);
568
+ int ret;
569
+ unsigned int reg1, reg2, reg3;
570
+
571
+ val = clamp_val(val / 1000, -128, 127);
572
+
573
+ switch (attr) {
574
+ case hwmon_temp_max:
575
+ reg1 = LTD_HV_LL_REG;
576
+ reg2 = TEMP_CH1_W_REG;
577
+ reg3 = DTS_T_CPU1_W_REG;
578
+ break;
579
+ case hwmon_temp_max_hyst:
580
+ reg1 = LTD_LV_LL_REG;
581
+ reg2 = TEMP_CH1_WH_REG;
582
+ reg3 = DTS_T_CPU1_WH_REG;
583
+ break;
584
+ case hwmon_temp_crit:
585
+ reg1 = LTD_HV_HL_REG;
586
+ reg2 = TEMP_CH1_C_REG;
587
+ reg3 = DTS_T_CPU1_C_REG;
588
+ break;
589
+ case hwmon_temp_crit_hyst:
590
+ reg1 = LTD_LV_HL_REG;
591
+ reg2 = TEMP_CH1_CH_REG;
592
+ reg3 = DTS_T_CPU1_CH_REG;
593
+ break;
594
+ default:
595
+ return -EOPNOTSUPP;
596
+ }
597
+ if (channel == 4)
598
+ ret = nct7904_write_reg(data, BANK_1, reg1, val);
599
+ else if (channel < 5)
600
+ ret = nct7904_write_reg(data, BANK_1,
601
+ reg2 + channel * 8, val);
602
+ else
603
+ ret = nct7904_write_reg(data, BANK_1,
604
+ reg3 + (channel - 5) * 4, val);
605
+
606
+ return ret;
607
+}
608
+
609
+static int nct7904_write_fan(struct device *dev, u32 attr, int channel,
610
+ long val)
611
+{
612
+ struct nct7904_data *data = dev_get_drvdata(dev);
613
+ int ret;
614
+ u8 tmp;
615
+
616
+ switch (attr) {
617
+ case hwmon_fan_min:
618
+ if (val <= 0)
619
+ return -EINVAL;
620
+
621
+ val = clamp_val(DIV_ROUND_CLOSEST(1350000, val), 1, 0x1fff);
622
+ tmp = (val >> 5) & 0xff;
623
+ ret = nct7904_write_reg(data, BANK_1,
624
+ FANIN1_HV_HL_REG + channel * 2, tmp);
625
+ if (ret < 0)
626
+ return ret;
627
+ tmp = val & 0x1f;
628
+ ret = nct7904_write_reg(data, BANK_1,
629
+ FANIN1_LV_HL_REG + channel * 2, tmp);
630
+ return ret;
631
+ default:
632
+ return -EOPNOTSUPP;
633
+ }
634
+}
635
+
636
+static int nct7904_write_in(struct device *dev, u32 attr, int channel,
637
+ long val)
638
+{
639
+ struct nct7904_data *data = dev_get_drvdata(dev);
640
+ int ret, index, tmp;
641
+
642
+ index = nct7904_chan_to_index[channel];
643
+
644
+ if (index < 14)
645
+ val = val / 2; /* 0.002V scale */
646
+ else
647
+ val = val / 6; /* 0.006V scale */
648
+
649
+ val = clamp_val(val, 0, 0x7ff);
650
+
651
+ switch (attr) {
652
+ case hwmon_in_min:
653
+ tmp = nct7904_read_reg(data, BANK_1,
654
+ VSEN1_LV_LL_REG + index * 4);
655
+ if (tmp < 0)
656
+ return tmp;
657
+ tmp &= ~0x7;
658
+ tmp |= val & 0x7;
659
+ ret = nct7904_write_reg(data, BANK_1,
660
+ VSEN1_LV_LL_REG + index * 4, tmp);
661
+ if (ret < 0)
662
+ return ret;
663
+ tmp = nct7904_read_reg(data, BANK_1,
664
+ VSEN1_HV_LL_REG + index * 4);
665
+ if (tmp < 0)
666
+ return tmp;
667
+ tmp = (val >> 3) & 0xff;
668
+ ret = nct7904_write_reg(data, BANK_1,
669
+ VSEN1_HV_LL_REG + index * 4, tmp);
670
+ return ret;
671
+ case hwmon_in_max:
672
+ tmp = nct7904_read_reg(data, BANK_1,
673
+ VSEN1_LV_HL_REG + index * 4);
674
+ if (tmp < 0)
675
+ return tmp;
676
+ tmp &= ~0x7;
677
+ tmp |= val & 0x7;
678
+ ret = nct7904_write_reg(data, BANK_1,
679
+ VSEN1_LV_HL_REG + index * 4, tmp);
680
+ if (ret < 0)
681
+ return ret;
682
+ tmp = nct7904_read_reg(data, BANK_1,
683
+ VSEN1_HV_HL_REG + index * 4);
684
+ if (tmp < 0)
685
+ return tmp;
686
+ tmp = (val >> 3) & 0xff;
687
+ ret = nct7904_write_reg(data, BANK_1,
688
+ VSEN1_HV_HL_REG + index * 4, tmp);
689
+ return ret;
293690 default:
294691 return -EOPNOTSUPP;
295692 }
....@@ -325,7 +722,7 @@
325722 switch (attr) {
326723 case hwmon_pwm_input:
327724 case hwmon_pwm_enable:
328
- return S_IRUGO | S_IWUSR;
725
+ return 0644;
329726 default:
330727 return 0;
331728 }
....@@ -352,8 +749,14 @@
352749 u32 attr, int channel, long val)
353750 {
354751 switch (type) {
752
+ case hwmon_in:
753
+ return nct7904_write_in(dev, attr, channel, val);
754
+ case hwmon_fan:
755
+ return nct7904_write_fan(dev, attr, channel, val);
355756 case hwmon_pwm:
356757 return nct7904_write_pwm(dev, attr, channel, val);
758
+ case hwmon_temp:
759
+ return nct7904_write_temp(dev, attr, channel, val);
357760 default:
358761 return -EOPNOTSUPP;
359762 }
....@@ -400,89 +803,109 @@
400803 return 0;
401804 }
402805
403
-static const u32 nct7904_in_config[] = {
404
- HWMON_I_INPUT, /* dummy, skipped in is_visible */
405
- HWMON_I_INPUT,
406
- HWMON_I_INPUT,
407
- HWMON_I_INPUT,
408
- HWMON_I_INPUT,
409
- HWMON_I_INPUT,
410
- HWMON_I_INPUT,
411
- HWMON_I_INPUT,
412
- HWMON_I_INPUT,
413
- HWMON_I_INPUT,
414
- HWMON_I_INPUT,
415
- HWMON_I_INPUT,
416
- HWMON_I_INPUT,
417
- HWMON_I_INPUT,
418
- HWMON_I_INPUT,
419
- HWMON_I_INPUT,
420
- HWMON_I_INPUT,
421
- HWMON_I_INPUT,
422
- HWMON_I_INPUT,
423
- HWMON_I_INPUT,
424
- HWMON_I_INPUT,
425
- 0
426
-};
427
-
428
-static const struct hwmon_channel_info nct7904_in = {
429
- .type = hwmon_in,
430
- .config = nct7904_in_config,
431
-};
432
-
433
-static const u32 nct7904_fan_config[] = {
434
- HWMON_F_INPUT,
435
- HWMON_F_INPUT,
436
- HWMON_F_INPUT,
437
- HWMON_F_INPUT,
438
- HWMON_F_INPUT,
439
- HWMON_F_INPUT,
440
- HWMON_F_INPUT,
441
- HWMON_F_INPUT,
442
- 0
443
-};
444
-
445
-static const struct hwmon_channel_info nct7904_fan = {
446
- .type = hwmon_fan,
447
- .config = nct7904_fan_config,
448
-};
449
-
450
-static const u32 nct7904_pwm_config[] = {
451
- HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
452
- HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
453
- HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
454
- HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
455
- 0
456
-};
457
-
458
-static const struct hwmon_channel_info nct7904_pwm = {
459
- .type = hwmon_pwm,
460
- .config = nct7904_pwm_config,
461
-};
462
-
463
-static const u32 nct7904_temp_config[] = {
464
- HWMON_T_INPUT,
465
- HWMON_T_INPUT,
466
- HWMON_T_INPUT,
467
- HWMON_T_INPUT,
468
- HWMON_T_INPUT,
469
- HWMON_T_INPUT,
470
- HWMON_T_INPUT,
471
- HWMON_T_INPUT,
472
- HWMON_T_INPUT,
473
- 0
474
-};
475
-
476
-static const struct hwmon_channel_info nct7904_temp = {
477
- .type = hwmon_temp,
478
- .config = nct7904_temp_config,
479
-};
480
-
481806 static const struct hwmon_channel_info *nct7904_info[] = {
482
- &nct7904_in,
483
- &nct7904_fan,
484
- &nct7904_pwm,
485
- &nct7904_temp,
807
+ HWMON_CHANNEL_INFO(in,
808
+ /* dummy, skipped in is_visible */
809
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
810
+ HWMON_I_ALARM,
811
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
812
+ HWMON_I_ALARM,
813
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
814
+ HWMON_I_ALARM,
815
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
816
+ HWMON_I_ALARM,
817
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
818
+ HWMON_I_ALARM,
819
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
820
+ HWMON_I_ALARM,
821
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
822
+ HWMON_I_ALARM,
823
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
824
+ HWMON_I_ALARM,
825
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
826
+ HWMON_I_ALARM,
827
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
828
+ HWMON_I_ALARM,
829
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
830
+ HWMON_I_ALARM,
831
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
832
+ HWMON_I_ALARM,
833
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
834
+ HWMON_I_ALARM,
835
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
836
+ HWMON_I_ALARM,
837
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
838
+ HWMON_I_ALARM,
839
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
840
+ HWMON_I_ALARM,
841
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
842
+ HWMON_I_ALARM,
843
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
844
+ HWMON_I_ALARM,
845
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
846
+ HWMON_I_ALARM,
847
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
848
+ HWMON_I_ALARM,
849
+ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
850
+ HWMON_I_ALARM),
851
+ HWMON_CHANNEL_INFO(fan,
852
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
853
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
854
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
855
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
856
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
857
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
858
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
859
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
860
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
861
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
862
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
863
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM),
864
+ HWMON_CHANNEL_INFO(pwm,
865
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
866
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
867
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
868
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
869
+ HWMON_CHANNEL_INFO(temp,
870
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
871
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
872
+ HWMON_T_CRIT_HYST,
873
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
874
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
875
+ HWMON_T_CRIT_HYST,
876
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
877
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
878
+ HWMON_T_CRIT_HYST,
879
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
880
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
881
+ HWMON_T_CRIT_HYST,
882
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
883
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
884
+ HWMON_T_CRIT_HYST,
885
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
886
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
887
+ HWMON_T_CRIT_HYST,
888
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
889
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
890
+ HWMON_T_CRIT_HYST,
891
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
892
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
893
+ HWMON_T_CRIT_HYST,
894
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
895
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
896
+ HWMON_T_CRIT_HYST,
897
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
898
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
899
+ HWMON_T_CRIT_HYST,
900
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
901
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
902
+ HWMON_T_CRIT_HYST,
903
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
904
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
905
+ HWMON_T_CRIT_HYST,
906
+ HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
907
+ HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
908
+ HWMON_T_CRIT_HYST),
486909 NULL
487910 };
488911
....@@ -497,14 +920,103 @@
497920 .info = nct7904_info,
498921 };
499922
500
-static int nct7904_probe(struct i2c_client *client,
501
- const struct i2c_device_id *id)
923
+/*
924
+ * Watchdog Function
925
+ */
926
+static int nct7904_wdt_start(struct watchdog_device *wdt)
927
+{
928
+ struct nct7904_data *data = watchdog_get_drvdata(wdt);
929
+
930
+ /* Enable soft watchdog timer */
931
+ return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN);
932
+}
933
+
934
+static int nct7904_wdt_stop(struct watchdog_device *wdt)
935
+{
936
+ struct nct7904_data *data = watchdog_get_drvdata(wdt);
937
+
938
+ return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS);
939
+}
940
+
941
+static int nct7904_wdt_set_timeout(struct watchdog_device *wdt,
942
+ unsigned int timeout)
943
+{
944
+ struct nct7904_data *data = watchdog_get_drvdata(wdt);
945
+ /*
946
+ * The NCT7904 is very special in watchdog function.
947
+ * Its minimum unit is minutes. And wdt->timeout needs
948
+ * to match the actual timeout selected. So, this needs
949
+ * to be: wdt->timeout = timeout / 60 * 60.
950
+ * For example, if the user configures a timeout of
951
+ * 119 seconds, the actual timeout will be 60 seconds.
952
+ * So, wdt->timeout must then be set to 60 seconds.
953
+ */
954
+ wdt->timeout = timeout / 60 * 60;
955
+
956
+ return nct7904_write_reg(data, BANK_0, WDT_TIMER_REG,
957
+ wdt->timeout / 60);
958
+}
959
+
960
+static int nct7904_wdt_ping(struct watchdog_device *wdt)
961
+{
962
+ /*
963
+ * Note:
964
+ * NCT7904 does not support refreshing WDT_TIMER_REG register when
965
+ * the watchdog is active. Please disable watchdog before feeding
966
+ * the watchdog and enable it again.
967
+ */
968
+ struct nct7904_data *data = watchdog_get_drvdata(wdt);
969
+ int ret;
970
+
971
+ /* Disable soft watchdog timer */
972
+ ret = nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS);
973
+ if (ret < 0)
974
+ return ret;
975
+
976
+ /* feed watchdog */
977
+ ret = nct7904_write_reg(data, BANK_0, WDT_TIMER_REG, wdt->timeout / 60);
978
+ if (ret < 0)
979
+ return ret;
980
+
981
+ /* Enable soft watchdog timer */
982
+ return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN);
983
+}
984
+
985
+static unsigned int nct7904_wdt_get_timeleft(struct watchdog_device *wdt)
986
+{
987
+ struct nct7904_data *data = watchdog_get_drvdata(wdt);
988
+ int ret;
989
+
990
+ ret = nct7904_read_reg(data, BANK_0, WDT_TIMER_REG);
991
+ if (ret < 0)
992
+ return 0;
993
+
994
+ return ret * 60;
995
+}
996
+
997
+static const struct watchdog_info nct7904_wdt_info = {
998
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
999
+ WDIOF_MAGICCLOSE,
1000
+ .identity = "nct7904 watchdog",
1001
+};
1002
+
1003
+static const struct watchdog_ops nct7904_wdt_ops = {
1004
+ .owner = THIS_MODULE,
1005
+ .start = nct7904_wdt_start,
1006
+ .stop = nct7904_wdt_stop,
1007
+ .ping = nct7904_wdt_ping,
1008
+ .set_timeout = nct7904_wdt_set_timeout,
1009
+ .get_timeleft = nct7904_wdt_get_timeleft,
1010
+};
1011
+
1012
+static int nct7904_probe(struct i2c_client *client)
5021013 {
5031014 struct nct7904_data *data;
5041015 struct device *hwmon_dev;
5051016 struct device *dev = &client->dev;
5061017 int ret, i;
5071018 u32 mask;
1019
+ u8 val, bit;
5081020
5091021 data = devm_kzalloc(dev, sizeof(struct nct7904_data), GFP_KERNEL);
5101022 if (!data)
....@@ -538,10 +1050,76 @@
5381050 data->vsen_mask = mask;
5391051
5401052 /* CPU_TEMP attributes */
541
- ret = nct7904_read_reg16(data, BANK_0, DTS_T_CTRL0_REG);
1053
+ ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL0_REG);
5421054 if (ret < 0)
5431055 return ret;
544
- data->tcpu_mask = ((ret >> 8) & 0xf) | ((ret & 0xf) << 4);
1056
+
1057
+ if ((ret & 0x6) == 0x6)
1058
+ data->tcpu_mask |= 1; /* TR1 */
1059
+ if ((ret & 0x18) == 0x18)
1060
+ data->tcpu_mask |= 2; /* TR2 */
1061
+ if ((ret & 0x20) == 0x20)
1062
+ data->tcpu_mask |= 4; /* TR3 */
1063
+ if ((ret & 0x80) == 0x80)
1064
+ data->tcpu_mask |= 8; /* TR4 */
1065
+
1066
+ /* LTD */
1067
+ ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG);
1068
+ if (ret < 0)
1069
+ return ret;
1070
+ if ((ret & 0x02) == 0x02)
1071
+ data->tcpu_mask |= 0x10;
1072
+
1073
+ /* Multi-Function detecting for Volt and TR/TD */
1074
+ ret = nct7904_read_reg(data, BANK_0, VT_ADC_MD_REG);
1075
+ if (ret < 0)
1076
+ return ret;
1077
+
1078
+ data->temp_mode = 0;
1079
+ for (i = 0; i < 4; i++) {
1080
+ val = (ret >> (i * 2)) & 0x03;
1081
+ bit = (1 << i);
1082
+ if (val == VOLT_MONITOR_MODE) {
1083
+ data->tcpu_mask &= ~bit;
1084
+ } else if (val == THERMAL_DIODE_MODE && i < 2) {
1085
+ data->temp_mode |= bit;
1086
+ data->vsen_mask &= ~(0x06 << (i * 2));
1087
+ } else if (val == THERMISTOR_MODE) {
1088
+ data->vsen_mask &= ~(0x02 << (i * 2));
1089
+ } else {
1090
+ /* Reserved */
1091
+ data->tcpu_mask &= ~bit;
1092
+ data->vsen_mask &= ~(0x06 << (i * 2));
1093
+ }
1094
+ }
1095
+
1096
+ /* PECI */
1097
+ ret = nct7904_read_reg(data, BANK_2, PFE_REG);
1098
+ if (ret < 0)
1099
+ return ret;
1100
+ if (ret & 0x80) {
1101
+ data->enable_dts = 1; /* Enable DTS & PECI */
1102
+ } else {
1103
+ ret = nct7904_read_reg(data, BANK_2, TSI_CTRL_REG);
1104
+ if (ret < 0)
1105
+ return ret;
1106
+ if (ret & 0x80)
1107
+ data->enable_dts = 0x3; /* Enable DTS & TSI */
1108
+ }
1109
+
1110
+ /* Check DTS enable status */
1111
+ if (data->enable_dts) {
1112
+ ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL0_REG);
1113
+ if (ret < 0)
1114
+ return ret;
1115
+ data->has_dts = ret & 0xF;
1116
+ if (data->enable_dts & ENABLE_TSI) {
1117
+ ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL1_REG);
1118
+ if (ret < 0)
1119
+ return ret;
1120
+ data->has_dts |= (ret & 0xF) << 4;
1121
+ }
1122
+ }
5451123
5461124 for (i = 0; i < FANCTL_MAX; i++) {
5471125 ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + i);
....@@ -550,10 +1128,36 @@
5501128 data->fan_mode[i] = ret;
5511129 }
5521130
1131
+ /* Read all of SMI status register to clear alarms */
1132
+ for (i = 0; i < SMI_STS_MAX; i++) {
1133
+ ret = nct7904_read_reg(data, BANK_0, SMI_STS1_REG + i);
1134
+ if (ret < 0)
1135
+ return ret;
1136
+ }
1137
+
5531138 hwmon_dev =
5541139 devm_hwmon_device_register_with_info(dev, client->name, data,
5551140 &nct7904_chip_info, NULL);
556
- return PTR_ERR_OR_ZERO(hwmon_dev);
1141
+ ret = PTR_ERR_OR_ZERO(hwmon_dev);
1142
+ if (ret)
1143
+ return ret;
1144
+
1145
+ /* Watchdog initialization */
1146
+ data->wdt.ops = &nct7904_wdt_ops;
1147
+ data->wdt.info = &nct7904_wdt_info;
1148
+
1149
+ data->wdt.timeout = WATCHDOG_TIMEOUT * 60; /* Set default timeout */
1150
+ data->wdt.min_timeout = MIN_TIMEOUT;
1151
+ data->wdt.max_timeout = MAX_TIMEOUT;
1152
+ data->wdt.parent = &client->dev;
1153
+
1154
+ watchdog_init_timeout(&data->wdt, timeout * 60, &client->dev);
1155
+ watchdog_set_nowayout(&data->wdt, nowayout);
1156
+ watchdog_set_drvdata(&data->wdt, data);
1157
+
1158
+ watchdog_stop_on_unregister(&data->wdt);
1159
+
1160
+ return devm_watchdog_register_device(dev, &data->wdt);
5571161 }
5581162
5591163 static const struct i2c_device_id nct7904_id[] = {
....@@ -567,7 +1171,7 @@
5671171 .driver = {
5681172 .name = "nct7904",
5691173 },
570
- .probe = nct7904_probe,
1174
+ .probe_new = nct7904_probe,
5711175 .id_table = nct7904_id,
5721176 .detect = nct7904_detect,
5731177 .address_list = normal_i2c,