Hi all,

I recently built a new system with an ASRock B450M Pro4 motherboard. This
board has a Nuvoton NCT6779D chip to monitor temperatures, fans and
voltages. OpenBSD's lm(4) currently only supports the Nuvoton NCT6776F
chip, added by Marco Pfatschbacher in 2011:

https://marc.info/?l=openbsd-cvs&m=132318770131497&w=2

NetBSD's lm(4) gained support for several other Nuvoton chips in this
commit by SAITOH Masanobu in 2017:

http://mail-index.netbsd.org/source-changes/2017/07/11/msg086253.html

I have adapted the NetBSD code to OpenBSD and confirmed that it appears to
work correctly with my NCT6779D chip. With the attached patch, I get this
in dmesg:

wbsio0 at isa0 port 0x2e/2: NCT6779D rev 0x62
lm1 at wbsio0 port 0x290/8: NCT6779D

And here's the sensor data:

$ sysctl hw.sensors.lm1
hw.sensors.lm1.temp0=29.00 degC (MB Temperature)
hw.sensors.lm1.temp1=31.00 degC (CPU Temperature)
hw.sensors.lm1.temp2=78.00 degC (Aux Temp0)
hw.sensors.lm1.temp3=98.00 degC (Aux Temp1)
hw.sensors.lm1.temp4=22.50 degC (Aux Temp2)
hw.sensors.lm1.temp5=-23.00 degC (Aux Temp3)
hw.sensors.lm1.fan0=1095 RPM (System Fan)
hw.sensors.lm1.fan1=739 RPM (CPU Fan)
hw.sensors.lm1.fan2=400 RPM (Aux Fan0)
hw.sensors.lm1.fan3=0 RPM (Aux Fan1)
hw.sensors.lm1.fan4=387 RPM (Aux Fan2)
hw.sensors.lm1.volt0=0.74 VDC (VCore)
hw.sensors.lm1.volt1=2.16 VDC (VIN1)
hw.sensors.lm1.volt2=3.33 VDC (AVCC)
hw.sensors.lm1.volt3=3.33 VDC (+3.3V)
hw.sensors.lm1.volt4=21.56 VDC (VIN0)
hw.sensors.lm1.volt5=0.87 VDC (VIN8)
hw.sensors.lm1.volt6=0.59 VDC (VIN4)
hw.sensors.lm1.volt7=3.46 VDC (+3.3VSB)
hw.sensors.lm1.volt8=0.00 VDC (VBAT)
hw.sensors.lm1.volt9=0.00 VDC (VTT)
hw.sensors.lm1.volt10=0.45 VDC (VIN5)
hw.sensors.lm1.volt11=2.13 VDC (VIN6)
hw.sensors.lm1.volt12=3.38 VDC (VIN2)
hw.sensors.lm1.volt13=5.12 VDC (VIN3)
hw.sensors.lm1.volt14=1.81 VDC (VIN7)

The motherboard and CPU temperature values look very reasonable; the Aux
Temp values look like garbage, possibly because there aren't any other
sensors on this board? Fan values look reasonable. I am unsure about the
voltage values, but the ones that claim to be 3.3 volts look sane.

This is the first non-trivial patch I'm submitting and my C is pretty
rusty, so I would appreciate review and corrections. I don't have any
other systems with different Nuvoton chips to test, so I can't confirm
that this works for the other chips.

Could anyone please review this and help me get it into commit-ready shape?

Thanks,
Joe

-- 

Joe Gidi
j...@entropicblur.com

"You cannot buy skill." -- Ross Seyfried
Index: share/man/man4/lm.4
===================================================================
RCS file: /cvs/src/share/man/man4/lm.4,v
retrieving revision 1.25
diff -u -p -u -r1.25 lm.4
--- share/man/man4/lm.4	16 Jul 2013 16:05:49 -0000	1.25
+++ share/man/man4/lm.4	13 Dec 2019 22:49:02 -0000
@@ -82,7 +82,7 @@ National Semiconductor LM79
 .It
 National Semiconductor LM81
 .It
-Nuvoton NCT6776F
+Nuvoton NCT6775F, NCT6776F, NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D
 .It
 Winbond W83627HF, W83627THF, W83637HF and W83697HF
 .It
Index: sys/dev/ic/lm78.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/lm78.c,v
retrieving revision 1.24
diff -u -p -u -r1.24 lm78.c
--- sys/dev/ic/lm78.c	14 Mar 2015 03:38:47 -0000	1.24
+++ sys/dev/ic/lm78.c	13 Dec 2019 22:49:03 -0000
@@ -67,6 +67,7 @@ void wb_refresh_temp(struct lm_softc *, 
 void wb_refresh_fanrpm(struct lm_softc *, int);
 void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
 void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
+const char * wb_nct67xx_id2str(uint8_t);
 
 void as_refresh_temp(struct lm_softc *, int);
 
@@ -80,6 +81,20 @@ struct lm_chip lm_chips[] = {
 	{ def_match } /* Must be last */
 };
 
+struct {
+	uint8_t id;
+	const char *str;
+} nct_chips[] = {
+	{WBSIO_ID_NCT6775F, "NCT6775F"},
+	{WBSIO_ID_NCT6776F, "NCT6776F"},
+	{WBSIO_ID_NCT5104D, "NCT5104D or 610[246]D"},
+	{WBSIO_ID_NCT6779D, "NCT6779D"},
+	{WBSIO_ID_NCT6791D, "NCT6791D"},
+	{WBSIO_ID_NCT6792D, "NCT6792D"},
+	{WBSIO_ID_NCT6793D, "NCT6793D"},
+	{WBSIO_ID_NCT6795D, "NCT6795D"},
+};
+
 struct lm_sensor lm78_sensors[] = {
 	/* Voltage */
 	{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
@@ -215,6 +230,43 @@ struct lm_sensor nct6776f_sensors[] = {
 	{ NULL }
 };
 
+/* NCT6779D */
+struct lm_sensor nct6779d_sensors[] = {
+	/* Voltage */
+	{ "VCore", SENSOR_VOLTS_DC, 4, 0x80, lm_refresh_volt, RFACT_NONE / 2 },
+	{ "VIN1", SENSOR_VOLTS_DC, 4, 0x81, lm_refresh_volt, RFACT(56, 10) / 2 },
+	{ "AVCC", SENSOR_VOLTS_DC, 4, 0x82, lm_refresh_volt, RFACT(34, 34) / 2 },
+	{ "+3.3V", SENSOR_VOLTS_DC, 4, 0x83, lm_refresh_volt, RFACT(34, 34) / 2 },
+	{ "VIN0", SENSOR_VOLTS_DC, 4, 0x84, lm_refresh_volt, RFACT(48600, 10000) },
+	{ "VIN8", SENSOR_VOLTS_DC, 4, 0x85, lm_refresh_volt, RFACT_NONE / 2 },
+	{ "VIN4", SENSOR_VOLTS_DC, 4, 0x86, lm_refresh_volt, RFACT_NONE },
+	{ "+3.3VSB", SENSOR_VOLTS_DC, 4, 0x87, lm_refresh_volt, RFACT(34, 34) / 2 },
+	{ "VBAT", SENSOR_VOLTS_DC, 4, 0x88, lm_refresh_volt, RFACT_NONE },
+	{ "VTT", SENSOR_VOLTS_DC, 4, 0x89, lm_refresh_volt, RFACT_NONE },
+	{ "VIN5", SENSOR_VOLTS_DC, 4, 0x8a, lm_refresh_volt, RFACT_NONE },
+	{ "VIN6", SENSOR_VOLTS_DC, 4, 0x8b, lm_refresh_volt, RFACT_NONE },
+	{ "VIN2", SENSOR_VOLTS_DC, 4, 0x8c, lm_refresh_volt, RFACT_NONE },
+	{ "VIN3", SENSOR_VOLTS_DC, 4, 0x8d, lm_refresh_volt, RFACT(14414, 10000) },
+	{ "VIN7", SENSOR_VOLTS_DC, 4, 0x8e, lm_refresh_volt, RFACT_NONE / 2 },
+
+	/* Temperature */
+	{ "MB Temperature", SENSOR_TEMP, 4, 0x90, lm_refresh_temp, 0 },
+	{ "CPU Temperature", SENSOR_TEMP, 4, 0x91, wb_refresh_temp, 0 },
+	{ "Aux Temp0", SENSOR_TEMP, 4, 0x92, wb_refresh_temp, 0 },
+	{ "Aux Temp1", SENSOR_TEMP, 4, 0x93, wb_refresh_temp, 0 },
+	{ "Aux Temp2", SENSOR_TEMP, 4, 0x94, wb_refresh_temp, 0 },
+	{ "Aux Temp3", SENSOR_TEMP, 4, 0x95, wb_refresh_temp, 0 },
+
+	/* Fans */
+	{ "System Fan", SENSOR_FANRPM, 4, 0xc0, wb_nct6776f_refresh_fanrpm, 0 },
+	{ "CPU Fan", SENSOR_FANRPM, 4, 0xc2, wb_nct6776f_refresh_fanrpm, 0 },
+	{ "Aux Fan0", SENSOR_FANRPM, 4, 0xc4, wb_nct6776f_refresh_fanrpm, 0 },
+	{ "Aux Fan1", SENSOR_FANRPM, 4, 0xc6, wb_nct6776f_refresh_fanrpm, 0 },
+	{ "Aux Fan2", SENSOR_FANRPM, 4, 0xc8, wb_nct6776f_refresh_fanrpm, 0 },
+
+	{  NULL }
+};
+
 struct lm_sensor w83637hf_sensors[] = {
 	/* Voltage */
 	{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
@@ -489,6 +541,7 @@ def_match(struct lm_softc *sc)
 int
 wb_match(struct lm_softc *sc)
 {
+	const char *model = NULL;
 	int banksel, vendid, devid;
 
 	/* Read vendor ID */
@@ -526,12 +579,46 @@ wb_match(struct lm_softc *sc)
 		lm_setup_sensors(sc, w83627ehf_sensors);
 		break;
 	case WB_CHIPID_W83627DHG:
-		if (sc->sioid == WBSIO_ID_NCT6776F) {
-			printf(": NCT6776F\n");
-			lm_setup_sensors(sc, nct6776f_sensors);
+		model = wb_nct67xx_id2str(sc->sioid);
+		if (model != NULL) {
+			switch (sc->sioid) {
+			case WBSIO_ID_NCT6775F:
+				printf(": NCT6775F\n");
+				lm_setup_sensors(sc, nct6776f_sensors);
+				break;
+                        case WBSIO_ID_NCT6776F:
+				printf(": NCT6776F\n");
+				lm_setup_sensors(sc, nct6776f_sensors);
+				break;
+                        case WBSIO_ID_NCT5104D:
+				printf(": NCT5104D\n");
+				lm_setup_sensors(sc, nct6776f_sensors);
+				break;
+			case WBSIO_ID_NCT6779D:
+				printf(": NCT6779D\n");
+				lm_setup_sensors(sc, nct6779d_sensors);
+				break;
+			case WBSIO_ID_NCT6791D:
+				printf(": NCT6791D\n");
+				lm_setup_sensors(sc, nct6779d_sensors);
+				break;
+			case WBSIO_ID_NCT6792D:
+				printf(": NCT6792D\n");
+				lm_setup_sensors(sc, nct6779d_sensors);
+				break;
+			case WBSIO_ID_NCT6793D:
+				printf(": NCT6793D\n");
+				lm_setup_sensors(sc, nct6779d_sensors);
+				break;
+			case WBSIO_ID_NCT6795D:
+				printf(": NCT6795D\n");
+				lm_setup_sensors(sc, nct6779d_sensors);
+				break;
+			}
 		} else {
 			printf(": W83627DHG\n");
 			lm_setup_sensors(sc, w83627dhg_sensors);
+			break;
 		}
 		break;
 	case WB_CHIPID_W83637HF:
@@ -851,6 +938,20 @@ wb_nct6776f_refresh_fanrpm(struct lm_sof
 		sensor->flags &= ~SENSOR_FINVALID;
 		sensor->value = (datah << 8) | datal;
 	}
+}
+
+const char *
+wb_nct67xx_id2str(uint8_t id)
+{
+	int i;
+
+	for (i = 0; i < nitems(nct_chips); i++) {
+		if (nct_chips[i].id == id)
+			return nct_chips[i].str;
+}
+
+	/* Not Found */
+	return NULL;
 }
 
 void
Index: sys/dev/ic/lm78var.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/lm78var.h,v
retrieving revision 1.18
diff -u -p -u -r1.18 lm78var.h
--- sys/dev/ic/lm78var.h	15 Mar 2016 20:50:22 -0000	1.18
+++ sys/dev/ic/lm78var.h	13 Dec 2019 22:49:03 -0000
@@ -123,7 +123,7 @@
 #define WB_VREF			3600
 #define WB_W83627EHF_VREF	2048
 
-#define WB_MAX_SENSORS  19
+#define WB_MAX_SENSORS  36
 
 struct lm_softc;
 
Index: sys/dev/isa/wbsio.c
===================================================================
RCS file: /cvs/src/sys/dev/isa/wbsio.c,v
retrieving revision 1.10
diff -u -p -u -r1.10 wbsio.c
--- sys/dev/isa/wbsio.c	14 Mar 2015 03:38:47 -0000	1.10
+++ sys/dev/isa/wbsio.c	13 Dec 2019 22:49:03 -0000
@@ -110,8 +110,12 @@ wbsio_probe(struct device *parent, void 
 	case WBSIO_ID_W83627UHG:
 	case WBSIO_ID_W83637HF:
 	case WBSIO_ID_W83697HF:
+	case WBSIO_ID_NCT6775F:
 	case WBSIO_ID_NCT6776F:
 	case WBSIO_ID_NCT5104D:
+	case WBSIO_ID_NCT6779D:
+	case WBSIO_ID_NCT6791D:
+	case WBSIO_ID_NCT6792D:
 		ia->ipa_nio = 1;
 		ia->ipa_io[0].length = WBSIO_IOSIZE;
 		ia->ipa_nmem = 0;
@@ -170,8 +174,26 @@ wbsio_attach(struct device *parent, stru
 	case WBSIO_ID_W83697HF:
 		printf(": W83697HF");
 		break;
+	case WBSIO_ID_NCT6775F:
+		printf(": NCT6775F");
+		break;
 	case WBSIO_ID_NCT6776F:
 		printf(": NCT6776F");
+		break;
+	case WBSIO_ID_NCT6779D:
+		printf(": NCT6779D");
+		break;
+	case WBSIO_ID_NCT6791D:
+		printf(": NCT6791D");
+		break;
+	case WBSIO_ID_NCT6792D:
+		printf(": NCT6792D");
+		break;
+	case WBSIO_ID_NCT6793D:
+		printf(": NCT6793D");
+		break;
+	case WBSIO_ID_NCT6795D:
+		printf(": NCT6795D");
 		break;
 	case WBSIO_ID_NCT5104D:
 		printf(": NCT5104D");
Index: sys/dev/isa/wbsioreg.h
===================================================================
RCS file: /cvs/src/sys/dev/isa/wbsioreg.h,v
retrieving revision 1.4
diff -u -p -u -r1.4 wbsioreg.h
--- sys/dev/isa/wbsioreg.h	2 Jan 2015 23:02:54 -0000	1.4
+++ sys/dev/isa/wbsioreg.h	13 Dec 2019 22:49:03 -0000
@@ -42,8 +42,14 @@
 #define WBSIO_ID_W83627SF	0x59
 #define WBSIO_ID_W83637HF	0x70
 #define WBSIO_ID_W83697HF	0x60
+#define WBSIO_ID_NCT6775F	0xb4
 #define WBSIO_ID_NCT6776F	0xc3
 #define WBSIO_ID_NCT5104D	0xc4
+#define WBSIO_ID_NCT6779D	0xc5
+#define WBSIO_ID_NCT6791D	0xc8
+#define WBSIO_ID_NCT6792D	0xc9
+#define WBSIO_ID_NCT6793D	0xd1
+#define WBSIO_ID_NCT6795D	0xd3
 
 /* Logical Device Number (LDN) Assignments */
 #define WBSIO_LDN_HM		0x0b

Reply via email to