The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/intel/pchtherm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2020 Takanori Watanabe
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/module.h>
   33 #include <sys/errno.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/sysctl.h>
   37 #include <sys/syslog.h>
   38 #include <sys/bus.h>
   39 
   40 #include <machine/bus.h>
   41 #include <sys/rman.h>
   42 #include <machine/resource.h>
   43 #include <dev/pci/pcivar.h>
   44 #include <dev/pci/pcireg.h>
   45 
   46 #define PCHTHERM_REG_TEMP 0
   47 #define PCHTHERM_REG_TSC 4
   48 #define PCHTHERM_REG_TSS 6
   49 #define PCHTHERM_REG_TSEL 8
   50 #define PCHTHERM_REG_TSREL 0xa
   51 #define PCHTHERM_REG_TSMIC 0xc
   52 #define PCHTHERM_REG_CTT 0x10
   53 #define PCHTHERM_REG_TAHV 0x14
   54 #define PCHTHERM_REG_TALV 0x18
   55 #define PCHTHERM_REG_TSPM 0x1c
   56 #define PCHTHERM_REG_TL 0x40
   57 #define PCHTHERM_REG_TL2 0x50
   58 #define PCHTHERM_REG_PHL 0x60
   59 #define PCHTHERM_REG_PHLC 0x62
   60 #define PCHTHERM_REG_TAS 0x80
   61 #define PCHTHERM_REG_TSPIEN 0x82
   62 #define PCHTHERM_REG_TSGPEN 0x84
   63 #define PCHTHERM_REG_TCFD 0xf0
   64 #define PCHTHERM_GEN_LOCKDOWN 0x80
   65 #define PCHTHERM_GEN_ENABLE 1
   66 #define PCHTHERM_TEMP_FACTOR 5
   67 #define PCHTHERM_TEMP_ZERO 2231
   68 #define PCHTHERM_TEMP_MASK 0x1ff
   69 #define PCHTHERM_TL_T0 0
   70 #define PCHTHERM_TL_T1 10
   71 #define PCHTHERM_TL_T2 20
   72 #define PCHTHERM_TEMP_TO_IK(val) (((val) & PCHTHERM_TEMP_MASK) * \
   73                                   PCHTHERM_TEMP_FACTOR +       \
   74                                   PCHTHERM_TEMP_ZERO)
   75 
   76 struct pchtherm_softc
   77 {
   78         int tbarrid;
   79         struct resource *tbar;
   80         int enable;
   81         int ctten;
   82         int pmtemp;
   83         unsigned int pmtime;
   84 };
   85 
   86 static const struct pci_device_table pchtherm_devices[] =
   87 {
   88         { PCI_DEV(0x8086, 0x9c24),
   89           PCI_DESCR("Haswell Thermal Subsystem")},
   90         { PCI_DEV(0x8086, 0x8c24),
   91           PCI_DESCR("Haswell Thermal Subsystem")},
   92         { PCI_DEV(0x8086, 0x9ca4),
   93           PCI_DESCR("Wildcat Point Thermal Subsystem")},
   94         { PCI_DEV(0x8086, 0x9d31),
   95           PCI_DESCR("Skylake PCH Thermal Subsystem")},
   96         { PCI_DEV(0x8086, 0xa131),
   97           PCI_DESCR("Skylake PCH 100 Thermal Subsystem")},
   98         { PCI_DEV(0x8086, 0x9df9),
   99           PCI_DESCR("CannonLake-LP Thermal Subsystem")},
  100         { PCI_DEV(0x8086, 0xa379),
  101           PCI_DESCR("CannonLake-H Thermal Subsystem")},
  102         { PCI_DEV(0x8086, 0x02f9),
  103           PCI_DESCR("CometLake-LP Thermal Subsystem")},
  104         { PCI_DEV(0x8086, 0x06f9),
  105           PCI_DESCR("CometLake-H Thermal Subsystem")},
  106         { PCI_DEV(0x8086, 0xa1b1),
  107           PCI_DESCR("Lewisburg Thermal Subsystem")},
  108 };
  109 
  110 static int pchtherm_probe(device_t dev)
  111 {
  112         const struct pci_device_table *tbl;
  113 
  114         tbl = PCI_MATCH(dev, pchtherm_devices);
  115         if (tbl == NULL)
  116                 return (ENXIO);
  117         device_set_desc(dev, tbl->descr);
  118 
  119         return (BUS_PROBE_DEFAULT);
  120 
  121 }
  122 static int pchtherm_tltemp_sysctl(SYSCTL_HANDLER_ARGS)
  123 {
  124         struct pchtherm_softc *sc = oidp->oid_arg1;
  125         int regshift = oidp->oid_arg2;
  126         int temp;
  127         
  128         temp = bus_read_4(sc->tbar, PCHTHERM_REG_TL);
  129         temp >>= regshift;
  130         temp = PCHTHERM_TEMP_TO_IK(temp);
  131         
  132         return sysctl_handle_int(oidp, &temp, 0, req);
  133 }       
  134 static int pchtherm_temp_sysctl(SYSCTL_HANDLER_ARGS)
  135 {
  136         struct pchtherm_softc *sc = oidp->oid_arg1;
  137         int regoff = oidp->oid_arg2;
  138         int temp;
  139 
  140         temp = bus_read_2(sc->tbar, regoff);
  141         temp = PCHTHERM_TEMP_TO_IK(temp);
  142         
  143         return sysctl_handle_int(oidp, &temp, 0, req);
  144 }
  145 
  146 #define FLAG_PRINT(dev, str, val) device_printf                         \
  147         (dev, str " %s %sable\n",                                       \
  148          ((val) & 0x80)? "Locked" : "",                                 \
  149          ((val) & 0x1)? "En" : "Dis")
  150 
  151 static int pchtherm_attach(device_t dev)
  152 {
  153         struct pchtherm_softc *sc =  device_get_softc(dev);
  154         unsigned int val;
  155         int flag;
  156         int temp;
  157 
  158         sc->tbarrid = PCIR_BAR(0);
  159         sc->tbar = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  160                                           &sc->tbarrid, RF_ACTIVE|RF_SHAREABLE);
  161         if (sc->tbar == NULL) {
  162                 return (ENOMEM);
  163         }
  164         sc->enable = bus_read_1(sc->tbar, PCHTHERM_REG_TSEL);
  165         if (!(sc->enable & PCHTHERM_GEN_ENABLE )) {
  166                 if (sc->enable & PCHTHERM_GEN_LOCKDOWN) {
  167                         device_printf(dev, "Sensor not available\n");
  168                         return 0;
  169                 } else {
  170                         device_printf(dev, "Enabling Sensor\n");
  171                         bus_write_1(sc->tbar, PCHTHERM_REG_TSEL,
  172                                     PCHTHERM_GEN_ENABLE);
  173                         sc->enable = bus_read_1(sc->tbar, PCHTHERM_REG_TSEL);
  174                         if (!(sc->enable & PCHTHERM_GEN_ENABLE)) {
  175                                 device_printf(dev, "Sensor enable failed\n");
  176                                 return 0;
  177                         }
  178                 }
  179         }
  180         
  181         sc->ctten = bus_read_1(sc->tbar, PCHTHERM_REG_TSC);
  182         if (bootverbose) {
  183                 FLAG_PRINT(dev, "Catastrophic Power Down", sc->ctten);
  184         }
  185         val = bus_read_1(sc->tbar, PCHTHERM_REG_TSREL);
  186         if (bootverbose) {
  187                 FLAG_PRINT(dev, "SMBus report", val);
  188         }
  189         val = bus_read_1(sc->tbar, PCHTHERM_REG_TSMIC);
  190         if (bootverbose) {
  191                 FLAG_PRINT(dev, "SMI on alert", val);
  192         }
  193         val = bus_read_2(sc->tbar, PCHTHERM_REG_TSPM);
  194         flag = val >> 13;
  195         if (bootverbose) {
  196                 device_printf(dev, "TSPM: %b\n",
  197                               flag, "\2\3Lock\2DTSS0EN\1DSSOC0");
  198                 device_printf(dev, "MAX Thermal Sensor Shutdown Time %ds\n",
  199                               1<<((val>>9)&7));
  200         }
  201 
  202         temp = val & PCHTHERM_TEMP_MASK;
  203         sc->pmtemp = PCHTHERM_TEMP_TO_IK(temp);
  204         sc->pmtime = 1<<((val>>9)&7);
  205         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  206                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  207                         OID_AUTO, "pmtemp", CTLTYPE_INT|CTLFLAG_RD,
  208                         sc, PCHTHERM_REG_TSPM, pchtherm_temp_sysctl,
  209                         "IK", "Thermal sensor idle temperature");
  210         SYSCTL_ADD_U32(device_get_sysctl_ctx(dev),
  211                        SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  212                        OID_AUTO, "pmtime", CTLFLAG_RD,
  213                        &sc->pmtime, 0,"Thermal sensor idle duration");
  214 
  215         val = bus_read_4(sc->tbar, PCHTHERM_REG_TL);
  216         flag = val>>29;
  217 
  218         if (bootverbose) {
  219                 device_printf(dev, "Throttling %b\n",
  220                               flag, "\2\3Lock\2TT13EN\1TTEN");
  221         }
  222         
  223         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  224                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  225                         OID_AUTO, "t0temp", CTLTYPE_INT |CTLFLAG_RD,
  226                         sc, PCHTHERM_TL_T0, pchtherm_tltemp_sysctl,
  227                         "IK", "T0 temperature");
  228 
  229         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  230                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  231                         OID_AUTO, "t1temp", CTLTYPE_INT |CTLFLAG_RD,
  232                         sc, PCHTHERM_TL_T1, pchtherm_tltemp_sysctl,
  233                         "IK", "T1 temperature");
  234 
  235         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  236                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  237                         OID_AUTO, "t2temp", CTLTYPE_INT |CTLFLAG_RD,
  238                         sc, PCHTHERM_TL_T2, pchtherm_tltemp_sysctl,
  239                         "IK", "T2 temperature");
  240 
  241         val = bus_read_2(sc->tbar, PCHTHERM_REG_TL2);
  242         if (bootverbose) {
  243                 flag = val >>14;
  244                 device_printf(dev, "TL2 flag %b\n",
  245                               flag, "\2\1PMCTEN\2Lock");
  246         }
  247 
  248         /* If PHL is disable and lockdown, don't export it.*/
  249         val = bus_read_2(sc->tbar, PCHTHERM_REG_PHLC);
  250         val <<= 16;
  251         val |= bus_read_2(sc->tbar, PCHTHERM_REG_PHL);
  252         if ((val & 0x10000) != 0x10000) {
  253                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  254                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  255                                 OID_AUTO, "pch_hot_level",
  256                                 CTLTYPE_INT |CTLFLAG_RD,
  257                                 sc, PCHTHERM_REG_PHL,
  258                                 pchtherm_temp_sysctl, "IK",
  259                                 "PCH Hot level Temperature");
  260         }
  261 
  262         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  263                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  264                         OID_AUTO, "temperature", CTLTYPE_INT |CTLFLAG_RD,
  265                         sc, PCHTHERM_REG_TEMP,
  266                         pchtherm_temp_sysctl, "IK", "Current temperature");
  267         /*
  268          * If sensor enable bit is locked down, there is no way to change
  269          * alart values effectively. 
  270          */
  271         if (!(sc->enable & PCHTHERM_GEN_LOCKDOWN) ||
  272             bus_read_2(sc->tbar, PCHTHERM_REG_TAHV) != 0) {
  273                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  274                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  275                                 OID_AUTO, "tahv", CTLTYPE_INT |CTLFLAG_RD,
  276                                 sc, PCHTHERM_REG_TAHV,
  277                                 pchtherm_temp_sysctl, "IK",
  278                                 "Alart High temperature");
  279         }
  280            
  281         if (!(sc->enable & PCHTHERM_GEN_LOCKDOWN) ||
  282             bus_read_2(sc->tbar, PCHTHERM_REG_TALV) != 0) {
  283                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  284                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  285                                 OID_AUTO, "talv", CTLTYPE_INT |CTLFLAG_RD,
  286                                 sc, PCHTHERM_REG_TALV,
  287                                 pchtherm_temp_sysctl, "IK",
  288                                 "Alart Low temperature");
  289         }
  290         if (!(sc->ctten& PCHTHERM_GEN_LOCKDOWN) ||
  291             sc->ctten& PCHTHERM_GEN_ENABLE) {
  292                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  293                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  294                                 OID_AUTO, "ctt",
  295                                 CTLTYPE_INT |CTLFLAG_RD,
  296                                 sc, PCHTHERM_REG_CTT,
  297                                 pchtherm_temp_sysctl, "IK",
  298                                 "Catastrophic Trip Point");
  299         }
  300                 
  301         return 0;
  302 }
  303 static int pchtherm_detach(device_t dev)
  304 {
  305         struct pchtherm_softc *sc =  device_get_softc(dev);
  306         bus_release_resource(dev, SYS_RES_MEMORY, sc->tbarrid, sc->tbar);
  307 
  308         return 0;
  309 }
  310 static device_method_t pchtherm_methods[] =
  311 {
  312         DEVMETHOD(device_probe, pchtherm_probe),
  313         DEVMETHOD(device_attach, pchtherm_attach),
  314         DEVMETHOD(device_detach, pchtherm_detach),
  315 
  316         DEVMETHOD_END
  317 };
  318 static driver_t pchtherm_driver = {
  319         "pchtherm",
  320         pchtherm_methods,
  321         sizeof(struct pchtherm_softc)
  322 };
  323 
  324 static devclass_t pchtherm_devclass;
  325 DRIVER_MODULE(pchtherm, pci, pchtherm_driver, pchtherm_devclass, 0, 0);
  326 PCI_PNP_INFO(pchtherm_devices);

Cache object: d332fd0b946020bb59b7a5daa5122f7d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.