Bug 221071

Summary: NCT6779D - implement support for sensor readings
Product: Base System Reporter: Nils Beyer <nbe>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Only Me CC: avg, cem, emaste
Priority: --- Keywords: patch
Version: 11.1-RELEASE   
Hardware: amd64   
OS: Any   
Attachments:
Description Flags
My dirty LUA script to parse output of "superiotool -de"
none
NetBSD variant of the driver
none
shell script variant of the parser none

Description Nils Beyer 2017-07-28 16:00:55 UTC
Created attachment 184805 [details]
My dirty LUA script to parse output of "superiotool -de"

Hi,

there's no support for the sensor readings of the Nuvoton NCT6679D

Here's a link to the datasheet:

    http://v-comp.kiev.ua/download/NCT6779D.pdf

I think bank 4, registers 80h - 95h are the interesting ones. The userspace program "superiotool" is able to read the register values, but I don't know how to interpret them correctly.

I've created a dirty LUA script to parse the output of "superiotool -de" as attachment to this report. Judging by that my CPU is only at 52°C during being fully loaded (Ryzen 1700 stock). That cannot be.

Maybe a userspace sensor reader would work as well as a kernel module, no idea. NetBSD also has a driver for reading the values - I've attached that file as well.

Would be nice to monitor these sensors in FreeBSD, too. Can anyone jump in?



Thanks in advance,
Nils
Comment 1 Nils Beyer 2017-07-28 16:01:25 UTC
Created attachment 184806 [details]
NetBSD variant of the driver
Comment 2 Nils Beyer 2017-07-28 17:55:53 UTC
I don't get it; for instance, CPU temperature - bank 4, register 91h reads
36h = 54

so, the logic in NetBSD code is as following:
-----------------------------------------------------------------------
        data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
        data += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
        if (data > 0xfffffff || (data > 0x0fa && data < 0x1a6)) {
                sc->sensors[n].state = ENVSYS_SINVALID;
        } else {
                if (data & 0x100)
                        data -= 0x200;
                sc->sensors[n].state = ENVSYS_SVALID;
                sc->sensors[n].value_cur = data * 500000 + 273150000;
        }
-----------------------------------------------------------------------

1) shift original value one left -> 6Ch = 108
2) shift value of next register seven right (0) and add that to original value -> 6Ch stays
2) bit-and that with 100h, if true then subtract 200h -> it's false, so 6Ch stays
3) multiply that with 500000 -> 0337f980h = 54000000
4) add 273150000 -> 137FE9B0h = 327150000

So, I have exceeded the safe temperature of my CPU and of the solar system's sun...
Comment 3 Andriy Gapon freebsd_committer freebsd_triage 2017-07-28 19:54:59 UTC
(In reply to Nils Beyer from comment #0)
At present FreeBSD does not have any kernel infrastructure for sensor monitoring...
Comment 4 Andriy Gapon freebsd_committer freebsd_triage 2017-07-28 19:56:38 UTC
(In reply to Nils Beyer from comment #2)
The resulting value is apparently in units of 10^-6 degrees Kelvin.
273.15 is a big hint right there.
Comment 5 Nils Beyer 2017-07-31 18:07:49 UTC
(In reply to Andriy Gapon from comment #4)

okay, so the value that "superiotool -de" spits out already is the current temperature in °C. Got it.

What about VCORE voltage. This is the logic:
----------------------------------------------------------------------------
#define RFACT_NONE      10000

+

        {
                .desc = "VCore",
                .type = ENVSYS_SVOLTS_DC,
                .bank = 4,
                .reg = 0x80,
                .refresh = lm_refresh_volt,
                .rfact = RFACT_NONE / 2
        },

+

        data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
        if (data == 0xff) {
                sc->sensors[n].state = ENVSYS_SINVALID;
        } else {
                sc->sensors[n].value_cur = (data << 4);
                if (sc->sensors[n].rfact) {
                        sc->sensors[n].value_cur *= sc->sensors[n].rfact;
                        sc->sensors[n].value_cur /= 10;
                } else {
                        sc->sensors[n].value_cur *= sc->lm_sensors[n].rfact;
                        sc->sensors[n].value_cur /= 10;
                        sc->sensors[n].rfact = sc->lm_sensors[n].rfact;
                }
                sc->sensors[n].state = ENVSYS_SVALID;
        }
----------------------------------------------------------------------------

bank 4, register 0x80 reads: 0x42 -> 66

1) it's not 0xff, so go on
2) shift left by 4 -> 1056 (I'll keep decimal for now)
3) "rfact" is set (I think), so multiply that with "rfact" (5000) -> 5280000
4) divide that with 10 -> 528000

So my CPU is running with 528000V or (if millivolts: 528V). Lovely, hard to cool it, though...
Comment 6 Nils Beyer 2017-08-02 20:02:11 UTC
Created attachment 184967 [details]
shell script variant of the parser