LCOV - code coverage report
Current view: top level - dev/pci - kate.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 85 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: kate.c,v 1.6 2015/03/14 03:38:48 jsg Exp $    */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <sys/param.h>
      20             : #include <sys/systm.h>
      21             : #include <sys/device.h>
      22             : #include <sys/sensors.h>
      23             : 
      24             : #include <dev/pci/pcireg.h>
      25             : #include <dev/pci/pcivar.h>
      26             : #include <dev/pci/pcidevs.h>
      27             : 
      28             : 
      29             : /*
      30             :  * AMD NPT Family 0Fh Processors, Function 3 -- Miscellaneous Control
      31             :  */
      32             : 
      33             : /* Function 3 Registers */
      34             : #define K_THERMTRIP_STAT_R      0xe4
      35             : #define K_NORTHBRIDGE_CAP_R     0xe8
      36             : #define K_CPUID_FAMILY_MODEL_R  0xfc
      37             : 
      38             : /* Bits within Thermtrip Status Register */
      39             : #define K_THERM_SENSE_SEL       (1 << 6)
      40             : #define K_THERM_SENSE_CORE_SEL  (1 << 2)
      41             : 
      42             : /* Flip core and sensor selection bits */
      43             : #define K_T_SEL_C0(v)           (v |= K_THERM_SENSE_CORE_SEL)
      44             : #define K_T_SEL_C1(v)           (v &= ~(K_THERM_SENSE_CORE_SEL))
      45             : #define K_T_SEL_S0(v)           (v &= ~(K_THERM_SENSE_SEL))
      46             : #define K_T_SEL_S1(v)           (v |= K_THERM_SENSE_SEL)
      47             : 
      48             : 
      49             : /*
      50             :  * Revision Guide for AMD NPT Family 0Fh Processors, 
      51             :  * Publication # 33610, Revision 3.30, February 2008
      52             :  */
      53             : static const struct {
      54             :         const char      rev[5];
      55             :         const pcireg_t  cpuid[5];
      56             : } kate_proc[] = {
      57             :         { "BH-F", { 0x00040FB0, 0x00040F80, 0, 0, 0 } },      /* F2 */
      58             :         { "DH-F", { 0x00040FF0, 0x00050FF0, 0x00040FC0, 0, 0 } }, /* F2, F3 */
      59             :         { "JH-F", { 0x00040F10, 0x00040F30, 0x000C0F10, 0, 0 } }, /* F2, F3 */
      60             :         { "BH-G", { 0x00060FB0, 0x00060F80, 0, 0, 0 } },      /* G1, G2 */
      61             :         { "DH-G", { 0x00070FF0, 0x00060FF0,
      62             :             0x00060FC0, 0x00070FC0, 0 } }       /* G1, G2 */
      63             : };
      64             : 
      65             : 
      66             : struct kate_softc {
      67             :         struct device           sc_dev;
      68             : 
      69             :         pci_chipset_tag_t       sc_pc;
      70             :         pcitag_t                sc_pcitag;
      71             : 
      72             :         struct ksensor          sc_sensors[4];
      73             :         struct ksensordev       sc_sensordev;
      74             : 
      75             :         char                    sc_rev;
      76             :         int8_t                  sc_numsensors;
      77             : };
      78             : 
      79             : int     kate_match(struct device *, void *, void *);
      80             : void    kate_attach(struct device *, struct device *, void *);
      81             : void    kate_refresh(void *);
      82             : 
      83             : struct cfattach kate_ca = {
      84             :         sizeof(struct kate_softc), kate_match, kate_attach
      85             : };
      86             : 
      87             : struct cfdriver kate_cd = {
      88             :         NULL, "kate", DV_DULL
      89             : };
      90             : 
      91             : 
      92             : int
      93           0 : kate_match(struct device *parent, void *match, void *aux)
      94             : {
      95           0 :         struct pci_attach_args  *pa = aux;
      96             : #ifndef KATE_STRICT
      97           0 :         struct kate_softc       ks;
      98             :         struct kate_softc       *sc = &ks;
      99             : #endif /* !KATE_STRICT */
     100             :         pcireg_t                c;
     101             :         int                     i, j;
     102             : 
     103           0 :         if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD ||
     104           0 :             PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_AMD_AMD64_0F_MISC)
     105           0 :                 return 0;
     106             : 
     107             :         /*
     108             :          * First, let's probe for chips at or after Revision F, which is 
     109             :          * when the temperature readings were officially introduced.
     110             :          */
     111           0 :         c = pci_conf_read(pa->pa_pc, pa->pa_tag, K_CPUID_FAMILY_MODEL_R);
     112           0 :         for (i = 0; i < sizeof(kate_proc) / sizeof(kate_proc[0]); i++)
     113           0 :                 for (j = 0; kate_proc[i].cpuid[j] != 0; j++)
     114           0 :                         if ((c & ~0xf) == kate_proc[i].cpuid[j])
     115           0 :                                 return 2;       /* supersede pchb(4) */
     116             : 
     117             : #ifndef KATE_STRICT
     118             :         /*
     119             :          * If the probe above was not successful, let's try to actually
     120             :          * read the sensors from the chip, and see if they make any sense.
     121             :          */
     122           0 :         sc->sc_numsensors = 4;
     123           0 :         sc->sc_pc = pa->pa_pc;
     124           0 :         sc->sc_pcitag = pa->pa_tag;
     125           0 :         kate_refresh(sc);
     126           0 :         for (i = 0; i < sc->sc_numsensors; i++)
     127           0 :                 if (!(sc->sc_sensors[i].flags & SENSOR_FINVALID))
     128           0 :                         return 2;       /* supersede pchb(4) */
     129             : #endif /* !KATE_STRICT */
     130             : 
     131           0 :         return 0;
     132           0 : }
     133             : 
     134             : void
     135           0 : kate_attach(struct device *parent, struct device *self, void *aux)
     136             : {
     137           0 :         struct kate_softc       *sc = (struct kate_softc *)self;
     138           0 :         struct pci_attach_args  *pa = aux;
     139             :         pcireg_t                c, d;
     140             :         int                     i, j, cmpcap;
     141             : 
     142           0 :         c = pci_conf_read(pa->pa_pc, pa->pa_tag, K_CPUID_FAMILY_MODEL_R);
     143           0 :         for (i = 0; i < sizeof(kate_proc) / sizeof(kate_proc[0]) &&
     144           0 :             sc->sc_rev == '\0'; i++)
     145           0 :                 for (j = 0; kate_proc[i].cpuid[j] != 0; j++)
     146           0 :                         if ((c & ~0xf) == kate_proc[i].cpuid[j]) {
     147           0 :                                 sc->sc_rev = kate_proc[i].rev[3];
     148           0 :                                 printf(": core rev %.4s%.1x",
     149           0 :                                     kate_proc[i].rev, c & 0xf);
     150           0 :                         }
     151             : 
     152           0 :         if (c != 0x0 && sc->sc_rev == '\0') {
     153             :                 /* CPUID Family Model Register was introduced in Revision F */
     154           0 :                 sc->sc_rev = 'G';    /* newer than E, assume G */
     155           0 :                 printf(": cpuid 0x%x", c);
     156           0 :         }
     157             : 
     158           0 :         d = pci_conf_read(pa->pa_pc, pa->pa_tag, K_NORTHBRIDGE_CAP_R);
     159           0 :         cmpcap = (d >> 12) & 0x3;
     160             : 
     161           0 :         sc->sc_pc = pa->pa_pc;
     162           0 :         sc->sc_pcitag = pa->pa_tag;
     163             : 
     164             : #ifndef KATE_STRICT
     165           0 :         sc->sc_numsensors = 4;
     166           0 :         kate_refresh(sc);
     167           0 :         if (cmpcap == 0 &&
     168           0 :             (sc->sc_sensors[2].flags & SENSOR_FINVALID) &&
     169           0 :             (sc->sc_sensors[3].flags & SENSOR_FINVALID))
     170           0 :                 sc->sc_numsensors = 2;
     171             : #else
     172             :         sc->sc_numsensors = cmpcap ? 4 : 2;
     173             : #endif /* !KATE_STRICT */
     174             : 
     175           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     176             :             sizeof(sc->sc_sensordev.xname));
     177             : 
     178           0 :         for (i = 0; i < sc->sc_numsensors; i++) {
     179           0 :                 sc->sc_sensors[i].type = SENSOR_TEMP;
     180           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
     181             :         }
     182             : 
     183           0 :         if (sensor_task_register(sc, kate_refresh, 5) == NULL) {
     184           0 :                 printf(": unable to register update task\n");
     185           0 :                 return;
     186             :         }
     187             : 
     188           0 :         sensordev_install(&sc->sc_sensordev);
     189             : 
     190           0 :         printf("\n");
     191           0 : }
     192             : 
     193             : void
     194           0 : kate_refresh(void *arg)
     195             : {
     196           0 :         struct kate_softc       *sc = arg;
     197           0 :         struct ksensor          *s = sc->sc_sensors;
     198           0 :         int8_t                  n = sc->sc_numsensors;
     199             :         pcireg_t                t, m;
     200             :         int                     i, v;
     201             : 
     202           0 :         t = pci_conf_read(sc->sc_pc, sc->sc_pcitag, K_THERMTRIP_STAT_R);
     203             : 
     204           0 :         for (i = 0; i < n; i++) {
     205           0 :                 switch(i) {
     206             :                 case 0:
     207           0 :                         K_T_SEL_C0(t);
     208           0 :                         K_T_SEL_S0(t);
     209           0 :                         break;
     210             :                 case 1:
     211           0 :                         K_T_SEL_C0(t);
     212           0 :                         K_T_SEL_S1(t);
     213           0 :                         break;
     214             :                 case 2:
     215           0 :                         K_T_SEL_C1(t);
     216           0 :                         K_T_SEL_S0(t);
     217           0 :                         break;
     218             :                 case 3:
     219           0 :                         K_T_SEL_C1(t);
     220           0 :                         K_T_SEL_S1(t);
     221           0 :                         break;
     222             :                 }
     223           0 :                 m = t & (K_THERM_SENSE_CORE_SEL | K_THERM_SENSE_SEL);
     224           0 :                 pci_conf_write(sc->sc_pc, sc->sc_pcitag, K_THERMTRIP_STAT_R, t);
     225           0 :                 t = pci_conf_read(sc->sc_pc, sc->sc_pcitag, K_THERMTRIP_STAT_R);
     226           0 :                 v = 0x3ff & (t >> 14);
     227             : #ifdef KATE_STRICT
     228             :                 if (sc->sc_rev != 'G')
     229             :                         v &= ~0x3;
     230             : #endif /* KATE_STRICT */
     231           0 :                 if ((t & (K_THERM_SENSE_CORE_SEL | K_THERM_SENSE_SEL)) == m &&
     232           0 :                     (v & ~0x3) != 0)
     233           0 :                         s[i].flags &= ~SENSOR_FINVALID;
     234             :                 else
     235           0 :                         s[i].flags |= SENSOR_FINVALID;
     236           0 :                 s[i].value = (v * 250000 - 49000000) + 273150000;
     237             :         }
     238           0 : }

Generated by: LCOV version 1.13