On Sun, Apr 24, 2022 at 07:06:19PM +0200, Claudio Jeker wrote:
> On Ryzen CPUs each CCD has a temp sensor. If the CPU has CCDs (which
> excludes Zen APU CPUs) this should show additional temp info. This is
> based on info from the Linux k10temp driver.
> 
> Additionally use the MSRs defined in "Open-Source Register Reference For
> AMD Family 17h Processors" to measure the CPU core frequency.
> That should be the actuall speed of the CPU core during the measuring
> interval.
> 
> On my T14g2 the output is now for example:
> ksmn0.temp0                       63.88 degC          Tctl
> ksmn0.frequency0            3553141515.00 Hz          CPU0
> ksmn0.frequency1            3549080315.00 Hz          CPU2
> ksmn0.frequency2            3552369937.00 Hz          CPU4
> ksmn0.frequency3            3546055048.00 Hz          CPU6
> ksmn0.frequency4            3546854449.00 Hz          CPU8
> ksmn0.frequency5            3543869698.00 Hz          CPU10
> ksmn0.frequency6            3542551127.00 Hz          CPU12
> ksmn0.frequency7            4441623647.00 Hz          CPU14
> 
> It is intresting to watch turbo kick in and how temp causes the CPU to
> throttle.
> 
> I only tested this on systems with APUs so I could not thest the Tccd temp
> reporting.

With the frequence sensor moved to cpu(4) this just adds the Tccd
additional temparature sensors. It does not fix the duplication of the
ksmn(4) sensors. That needs to be fixed by no attaching on the duplicate
root complexes. How that is done I still need to figure out.

-- 
:wq Claudio

Index: ksmn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ksmn.c,v
retrieving revision 1.6
diff -u -p -r1.6 ksmn.c
--- ksmn.c      11 Mar 2022 18:00:50 -0000      1.6
+++ ksmn.c      25 Apr 2022 15:19:21 -0000
@@ -42,6 +42,7 @@
   *     [31:21]  Current reported temperature.
   */
 #define SMU_17H_THM    0x59800
+#define SMU_17H_CCD_THM(o, x)  (SMU_17H_THM + (o) + ((x) * 4))
 #define GET_CURTMP(r)  (((r) >> 21) & 0x7ff)
 
 /*
@@ -50,6 +51,8 @@
  */
 #define CURTMP_17H_RANGE_SEL   (1 << 19)
 #define CURTMP_17H_RANGE_ADJUST        490
+#define CURTMP_CCD_VALID       (1 << 11)
+#define CURTMP_CCD_MASK                0x7ff
 
 /*
  * Undocumented tCTL offsets gleamed from Linux k10temp driver.
@@ -75,13 +78,18 @@ struct ksmn_softc {
        pcitag_t                sc_pcitag;
 
        int                     sc_tctl_offset;
+       unsigned int            sc_ccd_valid;           /* available Tccds */
+       unsigned int            sc_ccd_offset;
 
-       struct ksensor          sc_sensor;
        struct ksensordev       sc_sensordev;
+       struct ksensor          sc_sensor;              /* Tctl */
+       struct ksensor          sc_ccd_sensor[12];      /* Tccd */
 };
 
 int    ksmn_match(struct device *, void *, void *);
 void   ksmn_attach(struct device *, struct device *, void *);
+uint32_t       ksmn_read_reg(struct ksmn_softc *, uint32_t);
+void   ksmn_ccd_attach(struct ksmn_softc *, int);
 void   ksmn_refresh(void *);
 
 const struct cfattach ksmn_ca = {
@@ -113,7 +121,9 @@ ksmn_attach(struct device *parent, struc
        struct ksmn_softc       *sc = (struct ksmn_softc *)self;
        struct pci_attach_args  *pa = aux;
        struct curtmp_offset    *p;
-       extern char             cpu_model[];
+       struct cpu_info         *ci = curcpu();
+       extern char              cpu_model[];
+
 
        sc->sc_pc = pa->pa_pc;
        sc->sc_pcitag = pa->pa_tag;
@@ -122,6 +132,7 @@ ksmn_attach(struct device *parent, struc
            sizeof(sc->sc_sensordev.xname));
 
        sc->sc_sensor.type = SENSOR_TEMP;
+       snprintf(sc->sc_sensor.desc, sizeof(sc->sc_sensor.desc), "Tctl");
        sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
 
        /*
@@ -136,6 +147,38 @@ ksmn_attach(struct device *parent, struc
                        sc->sc_tctl_offset = p->tctl_offset;
        }
 
+       sc->sc_ccd_offset = 0x154;
+
+       if (ci->ci_family == 0x17 || ci->ci_family == 0x18) {
+               switch (ci->ci_model) {
+               case 0x1:       /* Zen */
+               case 0x8:       /* Zen+ */
+               case 0x11:      /* Zen APU */
+               case 0x18:      /* Zen+ APU */
+                       ksmn_ccd_attach(sc, 4);
+                       break;
+               case 0x31:      /* Zen2 Threadripper */
+               case 0x60:      /* Renoir */
+               case 0x68:      /* Lucienne */
+               case 0x71:      /* Zen2 */
+                       ksmn_ccd_attach(sc, 8);
+                       break;
+               }
+       } else if (ci->ci_family == 0x19) {
+               uint32_t m = ci->ci_model;
+
+               if ((m >= 0x40 && m <= 0x4f) ||
+                   (m >= 0x10 && m <= 0x1f) ||
+                   (m >= 0xa0 && m <= 0xaf))
+                       sc->sc_ccd_offset = 0x300;
+
+               if ((m >= 0x10 && m <= 0x1f) ||
+                   (m >= 0xa0 && m <= 0xaf))
+                       ksmn_ccd_attach(sc, 12);
+               else
+                       ksmn_ccd_attach(sc, 8);
+       }
+
        if (sensor_task_register(sc, ksmn_refresh, 5) == NULL) {
                printf(": unable to register update task\n");
                return;
@@ -146,18 +189,49 @@ ksmn_attach(struct device *parent, struc
        printf("\n");
 }
 
+uint32_t
+ksmn_read_reg(struct ksmn_softc *sc, uint32_t addr)
+{
+       uint32_t reg;
+       int s;
+
+       s = splhigh();
+       pci_conf_write(sc->sc_pc, sc->sc_pcitag, SMN_17H_ADDR_R, addr);
+       reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, SMN_17H_DATA_R);
+       splx(s);
+       return reg;
+}
+
+void
+ksmn_ccd_attach(struct ksmn_softc *sc, int nccd)
+{
+       struct ksensor *s;
+       uint32_t reg;
+       int i;
+
+       KASSERT(nccd > 0 && nccd < nitems(sc->sc_ccd_sensor));
+
+       for (i = 0; i < nccd; i++) {
+               reg = ksmn_read_reg(sc, SMU_17H_CCD_THM(sc->sc_ccd_offset, i));
+               if (reg & CURTMP_CCD_VALID) {
+                       sc->sc_ccd_valid |= (1 << i);
+                       s = &sc->sc_ccd_sensor[i];
+                       s->type = SENSOR_TEMP;
+                       snprintf(s->desc, sizeof(s->desc), "Tccd%d", i);
+                       sensor_attach(&sc->sc_sensordev, s);
+               }
+       }
+}
+
 void
 ksmn_refresh(void *arg)
 {
        struct ksmn_softc       *sc = arg;
        struct ksensor          *s = &sc->sc_sensor;
        pcireg_t                reg;
-       int                     raw, offset = 0;
-
-       pci_conf_write(sc->sc_pc, sc->sc_pcitag, SMN_17H_ADDR_R,
-           SMU_17H_THM);
-       reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, SMN_17H_DATA_R);
+       int                     i, raw, offset = 0;
 
+       reg = ksmn_read_reg(sc, SMU_17H_THM);
        raw = GET_CURTMP(reg);
        if ((reg & CURTMP_17H_RANGE_SEL) != 0)
                offset -= CURTMP_17H_RANGE_ADJUST;
@@ -166,5 +240,16 @@ ksmn_refresh(void *arg)
        offset *= 100000;
 
        /* convert raw (in steps of 0.125C) to uC, add offset, uC to uK. */
-       s->value = ((raw * 125000) + offset) + 273150000;
+       s->value = raw * 125000 + offset + 273150000;
+
+       offset = CURTMP_17H_RANGE_ADJUST * 100000;
+       for (i = 0; i < nitems(sc->sc_ccd_sensor); i++) {
+               if (sc->sc_ccd_valid & (1 << i)) {
+                       s = &sc->sc_ccd_sensor[i];
+                       reg = ksmn_read_reg(sc,
+                           SMU_17H_CCD_THM(sc->sc_ccd_offset, i));
+                       s->value = (reg & CURTMP_CCD_MASK) * 125000 - offset +
+                           273150000;
+               }
+       }
 }

Reply via email to