kate(4) and km(4): temperature sensors for AMD Family 0Fh, 10h and 11h AMD64 processors
authorConstantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
Sat, 13 Feb 2010 04:05:19 +0000 (23:05 -0500)
committerStathis Kamperis <beket@dragonflybsd.org>
Sat, 13 Feb 2010 13:59:24 +0000 (15:59 +0200)
13 files changed:
share/man/man4/Makefile
share/man/man4/kate.4 [new file with mode: 0644]
share/man/man4/km.4 [new file with mode: 0644]
sys/bus/pci/pcidevs
sys/bus/pci/pcidevs.h
sys/bus/pci/pcidevs_data.h
sys/conf/files
sys/config/LINT
sys/dev/powermng/Makefile
sys/dev/powermng/kate/Makefile [new file with mode: 0644]
sys/dev/powermng/kate/kate.c [new file with mode: 0644]
sys/dev/powermng/km/Makefile [new file with mode: 0644]
sys/dev/powermng/km/km.c [new file with mode: 0644]

index 033793b..60b896c 100644 (file)
@@ -123,9 +123,11 @@ MAN=       aac.4 \
        iwl.4 \
        jme.4 \
        joy.4 \
+       kate.4 \
        kbdmux.4 \
        keyboard.4 \
        kld.4 \
+       km.4 \
        ktr.4 \
        kue.4 \
        lge.4 \
diff --git a/share/man/man4/kate.4 b/share/man/man4/kate.4
new file mode 100644 (file)
index 0000000..987a181
--- /dev/null
@@ -0,0 +1,129 @@
+.\"    $OpenBSD: kate.4,v 1.1 2008/03/27 01:54:44 cnst Exp $
+.\"
+.\" Copyright (c) 2008/2010 Constantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd February 12, 2010
+.Dt KATE 4
+.Os
+.Sh NAME
+.Nm kate
+.Nd AMD K8 temperature sensor
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device kate"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following lines in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+kate_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the temperature sensors available in the
+AMD K8 family of processors.
+(Subsequent AMD families are supported by
+.Xr km 4 . )
+.Pp
+These sensors were officially introduced with
+Revision F Family 0Fh processors,
+and provide 1 degC accuracy.
+Precision was improved in Revision G chips,
+which provide two more bits for 0.25 degC steppings.
+Each core may have two temperature sensors, and
+there may be up to two cores per package.
+.Pp
+Multiprocessor systems would have one instance of
+.Nm
+per each chip.
+In each instance,
+.Va temp0
+and
+.Va temp1
+sensors
+correspond to the temperature sensors on the first core,
+whereas
+.Va temp2
+and
+.Va temp3
+correspond to the temperature sensors on the second core.
+As such, single core chips may have two sensors,
+and dual-core dual-processor systems may have as many as 8
+temperature sensors in total.
+.Pp
+Since many prior revisions of the chips appear to have
+valid readings for at least some temperature sensors
+in the same address space as the abovementioned revisions,
+the driver may also attach on such older revisions provided
+that it finds some sensor readings that appear valid.
+However, in such cases
+.Nm
+would not print the core revision information into the dmesg.
+.Pp
+Sensor values are made available through the
+.Dv HW_SENSORS
+.Xr sysctl 3
+interface,
+and can be monitored with the
+.Xr systat 1
+.Ar sensors
+display,
+.Xr sensorsd 8
+and
+.Xr sysctl 8
+.Ar hw.sensors .
+.Sh SEE ALSO
+.Xr systat 1 ,
+.Xr sysctl 3 ,
+.Xr intro 4 ,
+.Xr km 4 ,
+.Xr pci 4 ,
+.Xr sensorsd 8 ,
+.Xr sysctl 8
+.Rs
+.%T "BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors"
+.%D July 2007
+.%R Publication # 32559
+.%P pp. 21--23 and pp. 179--184
+.\" .%O http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
+.Re
+.Rs
+.%T "Revision Guide for AMD NPT Family 0Fh Processors"
+.%D February 2008
+.%R Publication # 33610
+.\" .%O http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.4
+and
+.Dx 2.5.1 .
+.Sh AUTHORS
+The
+.Nm
+driver was written for
+.Ox
+and
+.Dx
+by
+.An Constantine A. Murenin
+whilst at the University of Waterloo.
diff --git a/share/man/man4/km.4 b/share/man/man4/km.4
new file mode 100644 (file)
index 0000000..827d1a2
--- /dev/null
@@ -0,0 +1,111 @@
+.\"    $OpenBSD: km.4,v 1.5 2009/07/23 17:19:07 cnst Exp $
+.\"
+.\" Copyright (c) 2008/2010 Constantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd February 12, 2010
+.Dt KM 4
+.Os
+.Sh NAME
+.Nm km
+.Nd AMD K10 temperature sensor
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device km"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following lines in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+km_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the temperature sensors available in the
+AMD Family 10h and 11h processors.
+.Pp
+Each chip reports one temperature sensor.
+Multiprocessor systems have one instance of
+.Nm
+per chip.
+The highest resolution supported by the driver is 0.125 degC.
+.Pp
+Sensor values are made available through the
+.Dv HW_SENSORS
+.Xr sysctl 3
+interface,
+and can be monitored with the
+.Xr systat 1
+.Ar sensors
+display,
+.Xr sensorsd 8
+and
+.Xr sysctl 8
+.Ar hw.sensors .
+For example, with an
+.Tn AMD
+.Tn Phenom X4
+9850 Black Edition 2.5GHz
+.Tn Socket AM2+
+125W quad-core processor:
+.Bd -literal -offset indent
+%sysctl hw.sensors.km0
+hw.sensors.km0.temp0: 60.50 degC
+.Ed
+.Sh SEE ALSO
+.Xr systat 1 ,
+.Xr sysctl 3 ,
+.Xr intro 4 ,
+.Xr kate 4 ,
+.Xr pci 4 ,
+.Xr sensorsd 8 ,
+.Xr sysctl 8
+.Rs
+.%T "BIOS and Kernel Developer's Guide for AMD Family 10h Processors"
+.%D March 26, 2008
+.%R Publication # 31116
+.%P pp. 236--237 and pp. 243--244
+.\" .%O http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116.PDF
+.Re
+.Rs
+.%T "BIOS and Kernel Developer's Guide for AMD Family 11h Processors"
+.%D July 07, 2008
+.%R Publication # 41256
+.%P pp. 156--157 and pp. 159--160
+.\" .%O http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/41256.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.4
+and
+.Dx 2.5.1 .
+.Sh AUTHORS
+The
+.Nm
+driver was written for
+.Ox
+and
+.Dx
+by
+.An Constantine A. Murenin Aq http://cnst.su/ ,
+Raouf Boutaba Research Group,
+David R. Cheriton School of Computer Science,
+University of Waterloo.
index ba76486..9f385e5 100644 (file)
@@ -819,6 +819,16 @@ product AMD AMD64_HT       0x1100  AMD64 HyperTransport configuration
 product AMD AMD64_ADDR 0x1101  AMD64 Address Map configuration
 product AMD AMD64_DRAM 0x1102  AMD64 DRAM configuration
 product AMD AMD64_MISC 0x1103  AMD64 Miscellaneous configuration
+product AMD AMD64_F10_HT       0x1200  Family 10h HyperTransport
+product AMD AMD64_F10_ADDR     0x1201  Family 10h Address Map
+product AMD AMD64_F10_DRAM     0x1202  Family 10h DRAM
+product AMD AMD64_F10_MISC     0x1203  Family 10h Miscellaneous
+product AMD AMD64_F10_LINK     0x1204  Family 10h Link
+product AMD AMD64_F11_HT       0x1300  Family 11h HyperTransport
+product AMD AMD64_F11_ADDR     0x1301  Family 11h Address Map
+product AMD AMD64_F11_DRAM     0x1302  Family 11h DRAM
+product AMD AMD64_F11_MISC     0x1303  Family 11h Miscellaneous
+product AMD AMD64_F11_LINK     0x1304  Family 11h Link
 product AMD PCNET_PCI  0x2000  PCnet-PCI Ethernet
 product AMD PCNET_HOME 0x2001  PCnet-Home HomePNA Ethernet
 product AMD PCSCSI_PCI 0x2020  PCscsi-PCI SCSI
index ac1340d..35b12ef 100644 (file)
 #define        PCI_PRODUCT_AMD_AMD64_ADDR      0x1101          /* AMD64 Address Map configuration */
 #define        PCI_PRODUCT_AMD_AMD64_DRAM      0x1102          /* AMD64 DRAM configuration */
 #define        PCI_PRODUCT_AMD_AMD64_MISC      0x1103          /* AMD64 Miscellaneous configuration */
+#define        PCI_PRODUCT_AMD_AMD64_F10_HT    0x1200          /* Family 10h HyperTransport */
+#define        PCI_PRODUCT_AMD_AMD64_F10_ADDR  0x1201          /* Family 10h Address Map */
+#define        PCI_PRODUCT_AMD_AMD64_F10_DRAM  0x1202          /* Family 10h DRAM */
+#define        PCI_PRODUCT_AMD_AMD64_F10_MISC  0x1203          /* Family 10h Miscellaneous */
+#define        PCI_PRODUCT_AMD_AMD64_F10_LINK  0x1204          /* Family 10h Link */
+#define        PCI_PRODUCT_AMD_AMD64_F11_HT    0x1300          /* Family 11h HyperTransport */
+#define        PCI_PRODUCT_AMD_AMD64_F11_ADDR  0x1301          /* Family 11h Address Map */
+#define        PCI_PRODUCT_AMD_AMD64_F11_DRAM  0x1302          /* Family 11h DRAM */
+#define        PCI_PRODUCT_AMD_AMD64_F11_MISC  0x1303          /* Family 11h Miscellaneous */
+#define        PCI_PRODUCT_AMD_AMD64_F11_LINK  0x1304          /* Family 11h Link */
 #define        PCI_PRODUCT_AMD_PCNET_PCI       0x2000          /* PCnet-PCI Ethernet */
 #define        PCI_PRODUCT_AMD_PCNET_HOME      0x2001          /* PCnet-Home HomePNA Ethernet */
 #define        PCI_PRODUCT_AMD_PCSCSI_PCI      0x2020          /* PCscsi-PCI SCSI */
index e710fa1..e865c76 100644 (file)
@@ -1001,6 +1001,66 @@ const struct pci_knowndev pci_knowndevs[] = {
            "Advanced Micro Devices",
            "AMD64 Miscellaneous configuration",
        },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F10_HT,
+           0,
+           "Advanced Micro Devices",
+           "Family 10h HyperTransport",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F10_ADDR,
+           0,
+           "Advanced Micro Devices",
+           "Family 10h Address Map",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F10_DRAM,
+           0,
+           "Advanced Micro Devices",
+           "Family 10h DRAM",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F10_MISC,
+           0,
+           "Advanced Micro Devices",
+           "Family 10h Miscellaneous",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F10_LINK,
+           0,
+           "Advanced Micro Devices",
+           "Family 10h Link",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F11_HT,
+           0,
+           "Advanced Micro Devices",
+           "Family 11h HyperTransport",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F11_ADDR,
+           0,
+           "Advanced Micro Devices",
+           "Family 11h Address Map",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F11_DRAM,
+           0,
+           "Advanced Micro Devices",
+           "Family 11h DRAM",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F11_MISC,
+           0,
+           "Advanced Micro Devices",
+           "Family 11h Miscellaneous",
+       },
+       {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_F11_LINK,
+           0,
+           "Advanced Micro Devices",
+           "Family 11h Link",
+       },
        {
            PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNET_PCI,
            0,
index 4176600..352f1d1 100644 (file)
@@ -375,6 +375,8 @@ dev/netif/ie/if_ie.c                optional nowerror ie isa
 dev/powermng/ichsmb/ichsmb.c   optional ichsmb
 dev/powermng/ichsmb/ichsmb_pci.c       optional ichsmb pci
 dev/powermng/coretemp/coretemp.c       optional coretemp
+dev/powermng/kate/kate.c       optional kate pci
+dev/powermng/km/km.c           optional km pci
 dev/raid/ida/ida.c             optional ida
 dev/raid/ida/ida_disk.c        optional ida
 dev/raid/ida/ida_eisa.c        optional ida eisa
index 3976dec..7464456 100644 (file)
@@ -2091,6 +2091,10 @@ device           pcf0    at isa? port 0x320 irq 5
 # Intel Core and newer CPUs on-die digital thermal sensor support
 device         coretemp
 
+# AMD Family 0Fh, 10h and 11h temperature sensors
+device         kate
+device         km
+
 # HW monitoring devices lm(4), it(4) and nsclpcsio.
 device         lm0     at isa? port 0x290
 device         it0     at isa? port 0x290
index b5a1ec3..6f9f381 100644 (file)
@@ -1,7 +1,7 @@
 # $DragonFly: src/sys/dev/powermng/Makefile,v 1.2 2007/10/02 13:16:42 hasso Exp $
 #
 
-SUBDIR=        coretemp
+SUBDIR=        coretemp kate km
 .if ${MACHINE_ARCH} == "i386"
 SUBDIR+= powernow
 .endif
diff --git a/sys/dev/powermng/kate/Makefile b/sys/dev/powermng/kate/Makefile
new file mode 100644 (file)
index 0000000..d59d08d
--- /dev/null
@@ -0,0 +1,5 @@
+KMOD=          kate
+SRCS=          ${KMOD}.c
+SRCS+=         pci_if.h bus_if.h device_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/powermng/kate/kate.c b/sys/dev/powermng/kate/kate.c
new file mode 100644 (file)
index 0000000..60bc1c5
--- /dev/null
@@ -0,0 +1,274 @@
+/*     $OpenBSD: kate.c,v 1.2 2008/03/27 04:52:03 cnst Exp $   */
+
+/*
+ * Copyright (c) 2008/2010 Constantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/sensors.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcidevs.h>
+
+
+/*
+ * AMD NPT Family 0Fh Processors, Function 3 -- Miscellaneous Control
+ */
+
+/* Function 3 Registers */
+#define K_THERMTRIP_STAT_R     0xe4
+#define K_NORTHBRIDGE_CAP_R    0xe8
+#define K_CPUID_FAMILY_MODEL_R 0xfc
+
+/* Bits within Thermtrip Status Register */
+#define K_THERM_SENSE_SEL      (1 << 6)
+#define K_THERM_SENSE_CORE_SEL (1 << 2)
+
+/* Flip core and sensor selection bits */
+#define K_T_SEL_C0(v)          (v |= K_THERM_SENSE_CORE_SEL)
+#define K_T_SEL_C1(v)          (v &= ~(K_THERM_SENSE_CORE_SEL))
+#define K_T_SEL_S0(v)          (v &= ~(K_THERM_SENSE_SEL))
+#define K_T_SEL_S1(v)          (v |= K_THERM_SENSE_SEL)
+
+
+/*
+ * Revision Guide for AMD NPT Family 0Fh Processors,
+ * Publication # 33610, Revision 3.30, February 2008
+ */
+static const struct {
+       const char      rev[5];
+       const uint32_t  cpuid[5];
+} kate_proc[] = {
+       { "BH-F", { 0x00040FB0, 0x00040F80, 0, 0, 0 } },        /* F2 */
+       { "DH-F", { 0x00040FF0, 0x00050FF0, 0x00040FC0, 0, 0 } }, /* F2, F3 */
+       { "JH-F", { 0x00040F10, 0x00040F30, 0x000C0F10, 0, 0 } }, /* F2, F3 */
+       { "BH-G", { 0x00060FB0, 0x00060F80, 0, 0, 0 } },        /* G1, G2 */
+       { "DH-G", { 0x00070FF0, 0x00060FF0,
+           0x00060FC0, 0x00070FC0, 0 } }       /* G1, G2 */
+};
+
+
+struct kate_softc {
+       struct device           *sc_dev;
+
+       struct ksensor          sc_sensors[4];
+       struct ksensordev       sc_sensordev;
+
+       char                    sc_rev;
+       int8_t                  sc_ii;
+       int8_t                  sc_in;
+};
+
+static void    kate_identify(driver_t *, struct device *);
+static int     kate_probe(struct device *);
+static int     kate_attach(struct device *);
+static int     kate_detach(struct device *);
+static void    kate_refresh(void *);
+
+static device_method_t kate_methods[] = {
+       DEVMETHOD(device_identify,      kate_identify),
+       DEVMETHOD(device_probe,         kate_probe),
+       DEVMETHOD(device_attach,        kate_attach),
+       DEVMETHOD(device_detach,        kate_detach),
+       { NULL, NULL }
+};
+
+static driver_t kate_driver = {
+       "kate",
+       kate_methods,
+       sizeof(struct kate_softc)
+};
+
+static devclass_t kate_devclass;
+
+DRIVER_MODULE(kate, hostb, kate_driver, kate_devclass, NULL, NULL);
+
+
+static void
+kate_identify(driver_t *driver, struct device *parent)
+{
+       if (kate_probe(parent) == ENXIO)
+               return;
+       if (device_find_child(parent, driver->name, -1) != NULL)
+               return;
+       device_add_child(parent, driver->name, -1);
+}
+
+static int
+kate_probe(struct device *dev)
+{
+#ifndef KATE_STRICT
+       struct kate_softc       ks;
+       struct kate_softc       *sc = &ks;
+#endif
+       uint32_t                c;
+       int                     i, j;
+
+       if (pci_get_vendor(dev) != PCI_VENDOR_AMD ||
+           pci_get_device(dev) != PCI_PRODUCT_AMD_AMD64_MISC)
+               return ENXIO;
+
+       /* just in case we probe successfully, set the description */
+       if (device_get_desc(dev) == NULL)
+               device_set_desc(dev,
+                   "AMD Family 0Fh temperature sensors");
+
+       /*
+        * First, let's probe for chips at or after Revision F, which is
+        * when the temperature readings were officially introduced.
+        */
+       c = pci_read_config(dev, K_CPUID_FAMILY_MODEL_R, 4);
+       for (i = 0; i < sizeof(kate_proc) / sizeof(kate_proc[0]); i++)
+               for (j = 0; kate_proc[i].cpuid[j] != 0; j++)
+                       if ((c & ~0xf) == kate_proc[i].cpuid[j])
+                               return 0;
+
+#ifndef KATE_STRICT
+       /*
+        * If the probe above was not successful, let's try to actually
+        * read the sensors from the chip, and see if they make any sense.
+        */
+       sc->sc_ii = 0;
+       sc->sc_in = 4;
+       sc->sc_dev = dev;
+       kate_refresh(sc);
+       for (i = 0; i < 4; i++)
+               if (!(sc->sc_sensors[i].flags & SENSOR_FINVALID))
+                       return 0;
+#endif /* !KATE_STRICT */
+
+       return ENXIO;
+}
+
+static int
+kate_attach(struct device *dev)
+{
+       struct kate_softc       *sc;
+       uint32_t                c, d;
+       int                     i, j, cmpcap;
+
+       sc = device_get_softc(dev);
+       sc->sc_dev = dev;
+
+       c = pci_read_config(dev, K_CPUID_FAMILY_MODEL_R, 4);
+       for (i = 0; i < sizeof(kate_proc) / sizeof(kate_proc[0]) &&
+           sc->sc_rev == '\0'; i++)
+               for (j = 0; kate_proc[i].cpuid[j] != 0; j++)
+                       if ((c & ~0xf) == kate_proc[i].cpuid[j]) {
+                               sc->sc_rev = kate_proc[i].rev[3];
+                               device_printf(dev, "core rev %.4s%.1x",
+                                   kate_proc[i].rev, c & 0xf);
+                               break;
+                       }
+
+       if (c != 0x0 && sc->sc_rev == '\0') {
+               /* CPUID Family Model Register was introduced in Revision F */
+               sc->sc_rev = 'G';       /* newer than E, assume G */
+               device_printf(dev, "cpuid 0x%x", c);
+       }
+
+       d = pci_read_config(dev, K_NORTHBRIDGE_CAP_R, 4);
+       cmpcap = (d >> 12) & 0x3;
+
+#ifndef KATE_STRICT
+       sc->sc_ii = 0;
+       sc->sc_in = 4;
+       kate_refresh(sc);
+       if (cmpcap == 0) {
+               if ((sc->sc_sensors[0].flags & SENSOR_FINVALID) &&
+                   (sc->sc_sensors[1].flags & SENSOR_FINVALID))
+                       sc->sc_ii = 2;
+               if ((sc->sc_sensors[4].flags & SENSOR_FINVALID))
+                       sc->sc_in = 3;
+       }
+#else
+       sc->sc_ii = cmpcap ? 0 : 2;
+       sc->sc_in = 4;
+#endif /* !KATE_STRICT */
+
+       strlcpy(sc->sc_sensordev.xname, device_get_nameunit(dev),
+           sizeof(sc->sc_sensordev.xname));
+
+       for (i = sc->sc_ii; i < sc->sc_in; i++) {
+               sc->sc_sensors[i].type = SENSOR_TEMP;
+               sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
+       }
+
+       if (sensor_task_register(sc, kate_refresh, 5)) {
+               device_printf(dev, "unable to register update task\n");
+               return ENXIO;
+       }
+
+       sensordev_install(&sc->sc_sensordev);
+       return 0;
+}
+
+static int
+kate_detach(struct device *dev)
+{
+       struct kate_softc       *sc = device_get_softc(dev);
+
+       sensordev_deinstall(&sc->sc_sensordev);
+       sensor_task_unregister(sc);
+       return 0;
+}
+
+void
+kate_refresh(void *arg)
+{
+       struct kate_softc       *sc = arg;
+       struct ksensor          *s = sc->sc_sensors;
+       uint32_t                t, m;
+       int                     i, v;
+
+       t = pci_read_config(sc->sc_dev, K_THERMTRIP_STAT_R, 4);
+
+       for (i = sc->sc_ii; i < sc->sc_in; i++) {
+               switch(i) {
+               case 0:
+                       K_T_SEL_C0(t);
+                       K_T_SEL_S0(t);
+                       break;
+               case 1:
+                       K_T_SEL_C0(t);
+                       K_T_SEL_S1(t);
+                       break;
+               case 2:
+                       K_T_SEL_C1(t);
+                       K_T_SEL_S0(t);
+                       break;
+               case 3:
+                       K_T_SEL_C1(t);
+                       K_T_SEL_S1(t);
+                       break;
+               }
+               m = t & (K_THERM_SENSE_CORE_SEL | K_THERM_SENSE_SEL);
+               pci_write_config(sc->sc_dev, K_THERMTRIP_STAT_R, t, 4);
+               t = pci_read_config(sc->sc_dev, K_THERMTRIP_STAT_R, 4);
+               v = 0x3ff & (t >> 14);
+#ifdef KATE_STRICT
+               if (sc->sc_rev != 'G')
+                       v &= ~0x3;
+#endif /* KATE_STRICT */
+               if ((t & (K_THERM_SENSE_CORE_SEL | K_THERM_SENSE_SEL)) == m &&
+                   (v & ~0x3) != 0)
+                       s[i].flags &= ~SENSOR_FINVALID;
+               else
+                       s[i].flags |= SENSOR_FINVALID;
+               s[i].value = (v * 250000 - 49000000) + 273150000;
+       }
+}
diff --git a/sys/dev/powermng/km/Makefile b/sys/dev/powermng/km/Makefile
new file mode 100644 (file)
index 0000000..0495377
--- /dev/null
@@ -0,0 +1,5 @@
+KMOD=          km
+SRCS=          ${KMOD}.c
+SRCS+=         pci_if.h bus_if.h device_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/powermng/km/km.c b/sys/dev/powermng/km/km.c
new file mode 100644 (file)
index 0000000..bec2f15
--- /dev/null
@@ -0,0 +1,153 @@
+/*     $OpenBSD: km.c,v 1.2 2008/08/29 03:38:31 cnst Exp $     */
+
+/*
+ * Copyright (c) 2008/2010 Constantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/sensors.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcidevs.h>
+
+
+/*
+ * AMD Family 10h Processors, Function 3 -- Miscellaneous Control
+ */
+
+/* Function 3 Registers */
+#define KM_REP_TEMP_CONTR_R    0xa4
+#define KM_THERMTRIP_STAT_R    0xe4
+#define KM_NORTHBRIDGE_CAP_R   0xe8
+#define KM_CPUID_FAMILY_MODEL_R        0xfc
+
+/* Operations on Reported Temperature Control Register */
+#define KM_GET_CURTMP(r)       (((r) >> 21) & 0x7ff)
+
+/* Operations on Thermtrip Status Register */
+#define KM_GET_DIODEOFFSET(r)  (((r) >> 8) & 0x7f)
+
+
+struct km_softc {
+       struct device           *sc_dev;
+       struct ksensor          sc_sensor;
+       struct ksensordev       sc_sensordev;
+};
+
+static void    km_identify(driver_t *, struct device *);
+static int     km_probe(struct device *);
+static int     km_attach(struct device *);
+static int     km_detach(struct device *);
+static void    km_refresh(void *);
+
+static device_method_t km_methods[] = {
+       DEVMETHOD(device_identify,      km_identify),
+       DEVMETHOD(device_probe,         km_probe),
+       DEVMETHOD(device_attach,        km_attach),
+       DEVMETHOD(device_detach,        km_detach),
+       { NULL, NULL }
+};
+
+static driver_t km_driver = {
+       "km",
+       km_methods,
+       sizeof(struct km_softc)
+};
+
+static devclass_t km_devclass;
+
+DRIVER_MODULE(km, hostb, km_driver, km_devclass, NULL, NULL);
+
+
+static void
+km_identify(driver_t *driver, struct device *parent)
+{
+       if (km_probe(parent) == ENXIO)
+               return;
+       if (device_find_child(parent, driver->name, -1) != NULL)
+               return;
+       device_add_child(parent, driver->name, -1);
+}
+
+static int
+km_probe(struct device *dev)
+{
+       int ten = 0;
+
+       if (pci_get_vendor(dev) != PCI_VENDOR_AMD)
+               return ENXIO;
+
+       switch (pci_get_device(dev)) {
+       case PCI_PRODUCT_AMD_AMD64_F10_MISC:
+               ten = 1;
+               /* FALLTHROUGH */
+       case PCI_PRODUCT_AMD_AMD64_F11_MISC:
+               if (device_get_desc(dev) == NULL)
+                       device_set_desc(dev, ten ?
+                           "AMD Family 10h temperature sensor" :
+                           "AMD Family 11h temperature sensor");
+               return 0;
+       default:
+               return ENXIO;
+       }
+}
+
+static int
+km_attach(struct device *dev)
+{
+       struct km_softc *sc;
+
+       sc = device_get_softc(dev);
+       sc->sc_dev = dev;
+
+       strlcpy(sc->sc_sensordev.xname, device_get_nameunit(dev),
+           sizeof(sc->sc_sensordev.xname));
+
+       sc->sc_sensor.type = SENSOR_TEMP;
+       sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
+
+       if (sensor_task_register(sc, km_refresh, 5)) {
+               device_printf(dev, "unable to register update task\n");
+               return ENXIO;
+       }
+
+       sensordev_install(&sc->sc_sensordev);
+       return 0;
+}
+
+static int
+km_detach(struct device *dev)
+{
+       struct km_softc *sc = device_get_softc(dev);
+
+       sensordev_deinstall(&sc->sc_sensordev);
+       sensor_task_unregister(sc);
+       return 0;
+}
+
+static void
+km_refresh(void *arg)
+{
+       struct km_softc *sc = arg;
+       struct ksensor  *s = &sc->sc_sensor;
+       uint32_t        r;
+       int             c;
+
+       r = pci_read_config(sc->sc_dev, KM_REP_TEMP_CONTR_R, 4);
+       c = KM_GET_CURTMP(r);
+       s->value = c * 125000 + 273150000;
+}