1 /* $OpenBSD: km.c,v 1.8 2013/09/17 13:42:34 kettenis Exp $ */
4 * Copyright (c) 2008/2010 Constantine A. Murenin <cnst+dfly@bugmail.mojo.ru>
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.
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.
19 #include <sys/param.h>
20 #include <sys/systm.h>
22 #include <sys/sensors.h>
24 #include <machine/md_var.h>
25 #include <machine/specialreg.h>
27 #include <bus/pci/pcivar.h>
32 * AMD Family 10h/11h/14h/15h Processors, Function 3 -- Miscellaneous Control
35 /* Function 3 Registers */
36 #define KM_REP_TEMP_CONTR_R 0xa4
37 #define KM_THERMTRIP_STAT_R 0xe4
38 #define KM_NORTHBRIDGE_CAP_R 0xe8
39 #define KM_CPUID_FAMILY_MODEL_R 0xfc
41 /* Operations on Reported Temperature Control Register */
42 #define KM_GET_CURTMP(r) (((r) >> 21) & 0x7ff)
44 /* Operations on Thermtrip Status Register */
45 #define KM_GET_DIODEOFFSET(r) (((r) >> 8) & 0x7f)
50 struct ksensor sc_sensor
;
51 struct ksensordev sc_sensordev
;
54 static void km_identify(driver_t
*, device_t
);
55 static int km_probe(device_t
);
56 static int km_attach(device_t
);
57 static int km_detach(device_t
);
58 static void km_refresh(void *);
60 static device_method_t km_methods
[] = {
61 DEVMETHOD(device_identify
, km_identify
),
62 DEVMETHOD(device_probe
, km_probe
),
63 DEVMETHOD(device_attach
, km_attach
),
64 DEVMETHOD(device_detach
, km_detach
),
68 static driver_t km_driver
= {
71 sizeof(struct km_softc
)
74 static devclass_t km_devclass
;
76 DRIVER_MODULE(km
, hostb
, km_driver
, km_devclass
, NULL
, NULL
);
80 km_identify(driver_t
*driver
, device_t parent
)
82 if (km_probe(parent
) == ENXIO
)
84 if (device_find_child(parent
, driver
->name
, -1) != NULL
)
86 device_add_child(parent
, driver
->name
, -1);
90 km_probe(device_t dev
)
94 if (pci_get_vendor(dev
) != PCI_VENDOR_AMD
)
97 switch (pci_get_device(dev
)) {
98 case PCI_PRODUCT_AMD_AMD64_F10_MISC
:
99 desc
= "AMD Family 10h temperature sensor";
101 case PCI_PRODUCT_AMD_AMD64_F11_MISC
:
102 desc
= "AMD Family 11h temperature sensor";
104 case PCI_PRODUCT_AMD_AMD64_F14_MISC
:
105 if (CPUID_TO_FAMILY(cpu_id
) == 0x12)
106 desc
= "AMD Family 12h temperature sensor";
108 desc
= "AMD Family 14h temperature sensor";
110 case PCI_PRODUCT_AMD_AMD64_F15_0x_MISC
:
111 desc
= "AMD Family 15/0xh temperature sensor";
113 case PCI_PRODUCT_AMD_AMD64_F15_1x_MISC
:
114 desc
= "AMD Family 15/1xh temperature sensor";
116 case PCI_PRODUCT_AMD_AMD64_F15_3x_MISC
:
117 desc
= "AMD Family 15/3xh temperature sensor";
119 case PCI_PRODUCT_AMD_AMD64_F16_MISC
:
120 desc
= "AMD Family 16h temperature sensor";
126 if (device_get_desc(dev
) == NULL
)
127 device_set_desc(dev
, desc
);
132 km_attach(device_t dev
)
136 sc
= device_get_softc(dev
);
139 strlcpy(sc
->sc_sensordev
.xname
, device_get_nameunit(dev
),
140 sizeof(sc
->sc_sensordev
.xname
));
142 sc
->sc_sensor
.type
= SENSOR_TEMP
;
143 sensor_attach(&sc
->sc_sensordev
, &sc
->sc_sensor
);
145 sensor_task_register(sc
, km_refresh
, 5);
147 sensordev_install(&sc
->sc_sensordev
);
152 km_detach(device_t dev
)
154 struct km_softc
*sc
= device_get_softc(dev
);
156 sensordev_deinstall(&sc
->sc_sensordev
);
157 sensor_task_unregister(sc
);
162 km_refresh(void *arg
)
164 struct km_softc
*sc
= arg
;
165 struct ksensor
*s
= &sc
->sc_sensor
;
169 r
= pci_read_config(sc
->sc_dev
, KM_REP_TEMP_CONTR_R
, 4);
170 c
= KM_GET_CURTMP(r
);
171 s
->value
= c
* 125000 + 273150000;