36 37#include <sys/param.h> 38#include <sys/bus.h> 39#include <sys/conf.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/sysctl.h> 43#include <sys/systm.h> 44 45#include <machine/cpufunc.h> 46#include <machine/md_var.h> 47#include <machine/specialreg.h> 48 49#include <dev/pci/pcivar.h> 50#include <x86/pci_cfgreg.h> 51 52typedef enum { 53 CORE0_SENSOR0, 54 CORE0_SENSOR1, 55 CORE1_SENSOR0, 56 CORE1_SENSOR1, 57 CORE0, 58 CORE1 59} amdsensor_t; 60 61struct amdtemp_softc { 62 device_t sc_dev; 63 int sc_ncores; 64 int sc_ntemps; 65 int sc_flags; 66#define AMDTEMP_FLAG_CS_SWAP 0x01 /* ThermSenseCoreSel is inverted. */ 67#define AMDTEMP_FLAG_CT_10BIT 0x02 /* CurTmp is 10-bit wide. */ 68#define AMDTEMP_FLAG_ALT_OFFSET 0x04 /* CurTmp starts at -28C. */ 69 int32_t sc_offset; 70 int32_t (*sc_gettemp)(device_t, amdsensor_t); 71 struct sysctl_oid *sc_sysctl_cpu[MAXCPU]; 72 struct intr_config_hook sc_ich; 73}; 74 75#define VENDORID_AMD 0x1022 76#define DEVICEID_AMD_MISC0F 0x1103 77#define DEVICEID_AMD_MISC10 0x1203 78#define DEVICEID_AMD_MISC11 0x1303 79#define DEVICEID_AMD_MISC14 0x1703 80#define DEVICEID_AMD_MISC15 0x1603 81 82static struct amdtemp_product { 83 uint16_t amdtemp_vendorid; 84 uint16_t amdtemp_deviceid; 85} amdtemp_products[] = { 86 { VENDORID_AMD, DEVICEID_AMD_MISC0F }, 87 { VENDORID_AMD, DEVICEID_AMD_MISC10 }, 88 { VENDORID_AMD, DEVICEID_AMD_MISC11 }, 89 { VENDORID_AMD, DEVICEID_AMD_MISC14 }, 90 { VENDORID_AMD, DEVICEID_AMD_MISC15 }, 91 { 0, 0 } 92}; 93 94/* 95 * Reported Temperature Control Register 96 */ 97#define AMDTEMP_REPTMP_CTRL 0xa4 98 99/* 100 * Thermaltrip Status Register (Family 0Fh only) 101 */ 102#define AMDTEMP_THERMTP_STAT 0xe4 103#define AMDTEMP_TTSR_SELCORE 0x04 104#define AMDTEMP_TTSR_SELSENSOR 0x40 105 106/* 107 * DRAM Configuration High Register 108 */ 109#define AMDTEMP_DRAM_CONF_HIGH 0x94 /* Function 2 */ 110#define AMDTEMP_DRAM_MODE_DDR3 0x0100 111 112/* 113 * CPU Family/Model Register 114 */ 115#define AMDTEMP_CPUID 0xfc 116 117/* 118 * Device methods. 119 */ 120static void amdtemp_identify(driver_t *driver, device_t parent); 121static int amdtemp_probe(device_t dev); 122static int amdtemp_attach(device_t dev); 123static void amdtemp_intrhook(void *arg); 124static int amdtemp_detach(device_t dev); 125static int amdtemp_match(device_t dev); 126static int32_t amdtemp_gettemp0f(device_t dev, amdsensor_t sensor); 127static int32_t amdtemp_gettemp(device_t dev, amdsensor_t sensor); 128static int amdtemp_sysctl(SYSCTL_HANDLER_ARGS); 129 130static device_method_t amdtemp_methods[] = { 131 /* Device interface */ 132 DEVMETHOD(device_identify, amdtemp_identify), 133 DEVMETHOD(device_probe, amdtemp_probe), 134 DEVMETHOD(device_attach, amdtemp_attach), 135 DEVMETHOD(device_detach, amdtemp_detach), 136 137 {0, 0} 138}; 139 140static driver_t amdtemp_driver = { 141 "amdtemp", 142 amdtemp_methods, 143 sizeof(struct amdtemp_softc), 144}; 145 146static devclass_t amdtemp_devclass; 147DRIVER_MODULE(amdtemp, hostb, amdtemp_driver, amdtemp_devclass, NULL, NULL); 148 149static int 150amdtemp_match(device_t dev) 151{ 152 int i; 153 uint16_t vendor, devid; 154 155 vendor = pci_get_vendor(dev); 156 devid = pci_get_device(dev); 157 158 for (i = 0; amdtemp_products[i].amdtemp_vendorid != 0; i++) { 159 if (vendor == amdtemp_products[i].amdtemp_vendorid && 160 devid == amdtemp_products[i].amdtemp_deviceid) 161 return (1); 162 } 163 164 return (0); 165} 166 167static void 168amdtemp_identify(driver_t *driver, device_t parent) 169{ 170 device_t child; 171 172 /* Make sure we're not being doubly invoked. */ 173 if (device_find_child(parent, "amdtemp", -1) != NULL) 174 return; 175 176 if (amdtemp_match(parent)) { 177 child = device_add_child(parent, "amdtemp", -1); 178 if (child == NULL) 179 device_printf(parent, "add amdtemp child failed\n"); 180 } 181} 182 183static int 184amdtemp_probe(device_t dev) 185{ 186 uint32_t family, model; 187
| 36 37#include <sys/param.h> 38#include <sys/bus.h> 39#include <sys/conf.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/sysctl.h> 43#include <sys/systm.h> 44 45#include <machine/cpufunc.h> 46#include <machine/md_var.h> 47#include <machine/specialreg.h> 48 49#include <dev/pci/pcivar.h> 50#include <x86/pci_cfgreg.h> 51 52typedef enum { 53 CORE0_SENSOR0, 54 CORE0_SENSOR1, 55 CORE1_SENSOR0, 56 CORE1_SENSOR1, 57 CORE0, 58 CORE1 59} amdsensor_t; 60 61struct amdtemp_softc { 62 device_t sc_dev; 63 int sc_ncores; 64 int sc_ntemps; 65 int sc_flags; 66#define AMDTEMP_FLAG_CS_SWAP 0x01 /* ThermSenseCoreSel is inverted. */ 67#define AMDTEMP_FLAG_CT_10BIT 0x02 /* CurTmp is 10-bit wide. */ 68#define AMDTEMP_FLAG_ALT_OFFSET 0x04 /* CurTmp starts at -28C. */ 69 int32_t sc_offset; 70 int32_t (*sc_gettemp)(device_t, amdsensor_t); 71 struct sysctl_oid *sc_sysctl_cpu[MAXCPU]; 72 struct intr_config_hook sc_ich; 73}; 74 75#define VENDORID_AMD 0x1022 76#define DEVICEID_AMD_MISC0F 0x1103 77#define DEVICEID_AMD_MISC10 0x1203 78#define DEVICEID_AMD_MISC11 0x1303 79#define DEVICEID_AMD_MISC14 0x1703 80#define DEVICEID_AMD_MISC15 0x1603 81 82static struct amdtemp_product { 83 uint16_t amdtemp_vendorid; 84 uint16_t amdtemp_deviceid; 85} amdtemp_products[] = { 86 { VENDORID_AMD, DEVICEID_AMD_MISC0F }, 87 { VENDORID_AMD, DEVICEID_AMD_MISC10 }, 88 { VENDORID_AMD, DEVICEID_AMD_MISC11 }, 89 { VENDORID_AMD, DEVICEID_AMD_MISC14 }, 90 { VENDORID_AMD, DEVICEID_AMD_MISC15 }, 91 { 0, 0 } 92}; 93 94/* 95 * Reported Temperature Control Register 96 */ 97#define AMDTEMP_REPTMP_CTRL 0xa4 98 99/* 100 * Thermaltrip Status Register (Family 0Fh only) 101 */ 102#define AMDTEMP_THERMTP_STAT 0xe4 103#define AMDTEMP_TTSR_SELCORE 0x04 104#define AMDTEMP_TTSR_SELSENSOR 0x40 105 106/* 107 * DRAM Configuration High Register 108 */ 109#define AMDTEMP_DRAM_CONF_HIGH 0x94 /* Function 2 */ 110#define AMDTEMP_DRAM_MODE_DDR3 0x0100 111 112/* 113 * CPU Family/Model Register 114 */ 115#define AMDTEMP_CPUID 0xfc 116 117/* 118 * Device methods. 119 */ 120static void amdtemp_identify(driver_t *driver, device_t parent); 121static int amdtemp_probe(device_t dev); 122static int amdtemp_attach(device_t dev); 123static void amdtemp_intrhook(void *arg); 124static int amdtemp_detach(device_t dev); 125static int amdtemp_match(device_t dev); 126static int32_t amdtemp_gettemp0f(device_t dev, amdsensor_t sensor); 127static int32_t amdtemp_gettemp(device_t dev, amdsensor_t sensor); 128static int amdtemp_sysctl(SYSCTL_HANDLER_ARGS); 129 130static device_method_t amdtemp_methods[] = { 131 /* Device interface */ 132 DEVMETHOD(device_identify, amdtemp_identify), 133 DEVMETHOD(device_probe, amdtemp_probe), 134 DEVMETHOD(device_attach, amdtemp_attach), 135 DEVMETHOD(device_detach, amdtemp_detach), 136 137 {0, 0} 138}; 139 140static driver_t amdtemp_driver = { 141 "amdtemp", 142 amdtemp_methods, 143 sizeof(struct amdtemp_softc), 144}; 145 146static devclass_t amdtemp_devclass; 147DRIVER_MODULE(amdtemp, hostb, amdtemp_driver, amdtemp_devclass, NULL, NULL); 148 149static int 150amdtemp_match(device_t dev) 151{ 152 int i; 153 uint16_t vendor, devid; 154 155 vendor = pci_get_vendor(dev); 156 devid = pci_get_device(dev); 157 158 for (i = 0; amdtemp_products[i].amdtemp_vendorid != 0; i++) { 159 if (vendor == amdtemp_products[i].amdtemp_vendorid && 160 devid == amdtemp_products[i].amdtemp_deviceid) 161 return (1); 162 } 163 164 return (0); 165} 166 167static void 168amdtemp_identify(driver_t *driver, device_t parent) 169{ 170 device_t child; 171 172 /* Make sure we're not being doubly invoked. */ 173 if (device_find_child(parent, "amdtemp", -1) != NULL) 174 return; 175 176 if (amdtemp_match(parent)) { 177 child = device_add_child(parent, "amdtemp", -1); 178 if (child == NULL) 179 device_printf(parent, "add amdtemp child failed\n"); 180 } 181} 182 183static int 184amdtemp_probe(device_t dev) 185{ 186 uint32_t family, model; 187
|
188 family = CPUID_TO_FAMILY(cpu_id); 189 model = CPUID_TO_MODEL(cpu_id); 190 191 switch (family) { 192 case 0x0f: 193 if ((model == 0x04 && (cpu_id & CPUID_STEPPING) == 0) || 194 (model == 0x05 && (cpu_id & CPUID_STEPPING) <= 1)) 195 return (ENXIO); 196 break; 197 case 0x10: 198 case 0x11: 199 case 0x12: 200 case 0x14: 201 case 0x15: 202 break; 203 default: 204 return (ENXIO); 205 } 206 device_set_desc(dev, "AMD CPU On-Die Thermal Sensors"); 207 208 return (BUS_PROBE_GENERIC); 209} 210 211static int 212amdtemp_attach(device_t dev) 213{ 214 char tn[32]; 215 u_int regs[4]; 216 struct amdtemp_softc *sc = device_get_softc(dev); 217 struct sysctl_ctx_list *sysctlctx; 218 struct sysctl_oid *sysctlnode; 219 uint32_t cpuid, family, model; 220 u_int bid; 221 int erratum319, unit; 222 223 erratum319 = 0; 224 225 /* 226 * CPUID Register is available from Revision F. 227 */ 228 cpuid = cpu_id; 229 family = CPUID_TO_FAMILY(cpuid); 230 model = CPUID_TO_MODEL(cpuid); 231 if (family != 0x0f || model >= 0x40) { 232 cpuid = pci_read_config(dev, AMDTEMP_CPUID, 4); 233 family = CPUID_TO_FAMILY(cpuid); 234 model = CPUID_TO_MODEL(cpuid); 235 } 236 237 switch (family) { 238 case 0x0f: 239 /* 240 * Thermaltrip Status Register 241 * 242 * - ThermSenseCoreSel 243 * 244 * Revision F & G: 0 - Core1, 1 - Core0 245 * Other: 0 - Core0, 1 - Core1 246 * 247 * - CurTmp 248 * 249 * Revision G: bits 23-14 250 * Other: bits 23-16 251 * 252 * XXX According to the BKDG, CurTmp, ThermSenseSel and 253 * ThermSenseCoreSel bits were introduced in Revision F 254 * but CurTmp seems working fine as early as Revision C. 255 * However, it is not clear whether ThermSenseSel and/or 256 * ThermSenseCoreSel work in undocumented cases as well. 257 * In fact, the Linux driver suggests it may not work but 258 * we just assume it does until we find otherwise. 259 * 260 * XXX According to Linux, CurTmp starts at -28C on 261 * Socket AM2 Revision G processors, which is not 262 * documented anywhere. 263 */ 264 if (model >= 0x40) 265 sc->sc_flags |= AMDTEMP_FLAG_CS_SWAP; 266 if (model >= 0x60 && model != 0xc1) { 267 do_cpuid(0x80000001, regs); 268 bid = (regs[1] >> 9) & 0x1f; 269 switch (model) { 270 case 0x68: /* Socket S1g1 */ 271 case 0x6c: 272 case 0x7c: 273 break; 274 case 0x6b: /* Socket AM2 and ASB1 (2 cores) */ 275 if (bid != 0x0b && bid != 0x0c) 276 sc->sc_flags |= 277 AMDTEMP_FLAG_ALT_OFFSET; 278 break; 279 case 0x6f: /* Socket AM2 and ASB1 (1 core) */ 280 case 0x7f: 281 if (bid != 0x07 && bid != 0x09 && 282 bid != 0x0c) 283 sc->sc_flags |= 284 AMDTEMP_FLAG_ALT_OFFSET; 285 break; 286 default: 287 sc->sc_flags |= AMDTEMP_FLAG_ALT_OFFSET; 288 } 289 sc->sc_flags |= AMDTEMP_FLAG_CT_10BIT; 290 } 291 292 /* 293 * There are two sensors per core. 294 */ 295 sc->sc_ntemps = 2; 296 297 sc->sc_gettemp = amdtemp_gettemp0f; 298 break; 299 case 0x10: 300 /* 301 * Erratum 319 Inaccurate Temperature Measurement 302 * 303 * http://support.amd.com/us/Processor_TechDocs/41322.pdf 304 */ 305 do_cpuid(0x80000001, regs); 306 switch ((regs[1] >> 28) & 0xf) { 307 case 0: /* Socket F */ 308 erratum319 = 1; 309 break; 310 case 1: /* Socket AM2+ or AM3 */ 311 if ((pci_cfgregread(pci_get_bus(dev), 312 pci_get_slot(dev), 2, AMDTEMP_DRAM_CONF_HIGH, 2) & 313 AMDTEMP_DRAM_MODE_DDR3) != 0 || model > 0x04 || 314 (model == 0x04 && (cpuid & CPUID_STEPPING) >= 3)) 315 break; 316 /* XXX 00100F42h (RB-C2) exists in both formats. */ 317 erratum319 = 1; 318 break; 319 } 320 /* FALLTHROUGH */ 321 case 0x11: 322 case 0x12: 323 case 0x14: 324 case 0x15: 325 /* 326 * There is only one sensor per package. 327 */ 328 sc->sc_ntemps = 1; 329 330 sc->sc_gettemp = amdtemp_gettemp; 331 break; 332 } 333 334 /* Find number of cores per package. */ 335 sc->sc_ncores = (amd_feature2 & AMDID2_CMP) != 0 ? 336 (cpu_procinfo2 & AMDID_CMP_CORES) + 1 : 1; 337 if (sc->sc_ncores > MAXCPU) 338 return (ENXIO); 339 340 if (erratum319) 341 device_printf(dev, 342 "Erratum 319: temperature measurement may be inaccurate\n"); 343 if (bootverbose) 344 device_printf(dev, "Found %d cores and %d sensors.\n", 345 sc->sc_ncores, 346 sc->sc_ntemps > 1 ? sc->sc_ntemps * sc->sc_ncores : 1); 347 348 /* 349 * dev.amdtemp.N tree. 350 */ 351 unit = device_get_unit(dev); 352 snprintf(tn, sizeof(tn), "dev.amdtemp.%d.sensor_offset", unit); 353 TUNABLE_INT_FETCH(tn, &sc->sc_offset); 354 355 sysctlctx = device_get_sysctl_ctx(dev); 356 SYSCTL_ADD_INT(sysctlctx, 357 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 358 "sensor_offset", CTLFLAG_RW, &sc->sc_offset, 0, 359 "Temperature sensor offset"); 360 sysctlnode = SYSCTL_ADD_NODE(sysctlctx, 361 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 362 "core0", CTLFLAG_RD, 0, "Core 0"); 363 364 SYSCTL_ADD_PROC(sysctlctx, 365 SYSCTL_CHILDREN(sysctlnode), 366 OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD, 367 dev, CORE0_SENSOR0, amdtemp_sysctl, "IK", 368 "Core 0 / Sensor 0 temperature"); 369 370 if (sc->sc_ntemps > 1) { 371 SYSCTL_ADD_PROC(sysctlctx, 372 SYSCTL_CHILDREN(sysctlnode), 373 OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD, 374 dev, CORE0_SENSOR1, amdtemp_sysctl, "IK", 375 "Core 0 / Sensor 1 temperature"); 376 377 if (sc->sc_ncores > 1) { 378 sysctlnode = SYSCTL_ADD_NODE(sysctlctx, 379 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 380 OID_AUTO, "core1", CTLFLAG_RD, 0, "Core 1"); 381 382 SYSCTL_ADD_PROC(sysctlctx, 383 SYSCTL_CHILDREN(sysctlnode), 384 OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD, 385 dev, CORE1_SENSOR0, amdtemp_sysctl, "IK", 386 "Core 1 / Sensor 0 temperature"); 387 388 SYSCTL_ADD_PROC(sysctlctx, 389 SYSCTL_CHILDREN(sysctlnode), 390 OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD, 391 dev, CORE1_SENSOR1, amdtemp_sysctl, "IK", 392 "Core 1 / Sensor 1 temperature"); 393 } 394 } 395 396 /* 397 * Try to create dev.cpu sysctl entries and setup intrhook function. 398 * This is needed because the cpu driver may be loaded late on boot, 399 * after us. 400 */ 401 amdtemp_intrhook(dev); 402 sc->sc_ich.ich_func = amdtemp_intrhook; 403 sc->sc_ich.ich_arg = dev; 404 if (config_intrhook_establish(&sc->sc_ich) != 0) { 405 device_printf(dev, "config_intrhook_establish failed!\n"); 406 return (ENXIO); 407 } 408 409 return (0); 410} 411 412void 413amdtemp_intrhook(void *arg) 414{ 415 struct amdtemp_softc *sc; 416 struct sysctl_ctx_list *sysctlctx; 417 device_t dev = (device_t)arg; 418 device_t acpi, cpu, nexus; 419 amdsensor_t sensor; 420 int i; 421 422 sc = device_get_softc(dev); 423 424 /* 425 * dev.cpu.N.temperature. 426 */ 427 nexus = device_find_child(root_bus, "nexus", 0); 428 acpi = device_find_child(nexus, "acpi", 0); 429 430 for (i = 0; i < sc->sc_ncores; i++) { 431 if (sc->sc_sysctl_cpu[i] != NULL) 432 continue; 433 cpu = device_find_child(acpi, "cpu", 434 device_get_unit(dev) * sc->sc_ncores + i); 435 if (cpu != NULL) { 436 sysctlctx = device_get_sysctl_ctx(cpu); 437 438 sensor = sc->sc_ntemps > 1 ? 439 (i == 0 ? CORE0 : CORE1) : CORE0_SENSOR0; 440 sc->sc_sysctl_cpu[i] = SYSCTL_ADD_PROC(sysctlctx, 441 SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), 442 OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, 443 dev, sensor, amdtemp_sysctl, "IK", 444 "Current temparature"); 445 } 446 } 447 if (sc->sc_ich.ich_arg != NULL) 448 config_intrhook_disestablish(&sc->sc_ich); 449} 450 451int 452amdtemp_detach(device_t dev) 453{ 454 struct amdtemp_softc *sc = device_get_softc(dev); 455 int i; 456 457 for (i = 0; i < sc->sc_ncores; i++) 458 if (sc->sc_sysctl_cpu[i] != NULL) 459 sysctl_remove_oid(sc->sc_sysctl_cpu[i], 1, 0); 460 461 /* NewBus removes the dev.amdtemp.N tree by itself. */ 462 463 return (0); 464} 465 466static int 467amdtemp_sysctl(SYSCTL_HANDLER_ARGS) 468{ 469 device_t dev = (device_t)arg1; 470 struct amdtemp_softc *sc = device_get_softc(dev); 471 amdsensor_t sensor = (amdsensor_t)arg2; 472 int32_t auxtemp[2], temp; 473 int error; 474 475 switch (sensor) { 476 case CORE0: 477 auxtemp[0] = sc->sc_gettemp(dev, CORE0_SENSOR0); 478 auxtemp[1] = sc->sc_gettemp(dev, CORE0_SENSOR1); 479 temp = imax(auxtemp[0], auxtemp[1]); 480 break; 481 case CORE1: 482 auxtemp[0] = sc->sc_gettemp(dev, CORE1_SENSOR0); 483 auxtemp[1] = sc->sc_gettemp(dev, CORE1_SENSOR1); 484 temp = imax(auxtemp[0], auxtemp[1]); 485 break; 486 default: 487 temp = sc->sc_gettemp(dev, sensor); 488 break; 489 } 490 error = sysctl_handle_int(oidp, &temp, 0, req); 491 492 return (error); 493} 494 495#define AMDTEMP_ZERO_C_TO_K 2732 496 497static int32_t 498amdtemp_gettemp0f(device_t dev, amdsensor_t sensor) 499{ 500 struct amdtemp_softc *sc = device_get_softc(dev); 501 uint32_t mask, offset, temp; 502 503 /* Set Sensor/Core selector. */ 504 temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 1); 505 temp &= ~(AMDTEMP_TTSR_SELCORE | AMDTEMP_TTSR_SELSENSOR); 506 switch (sensor) { 507 case CORE0_SENSOR1: 508 temp |= AMDTEMP_TTSR_SELSENSOR; 509 /* FALLTHROUGH */ 510 case CORE0_SENSOR0: 511 case CORE0: 512 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) != 0) 513 temp |= AMDTEMP_TTSR_SELCORE; 514 break; 515 case CORE1_SENSOR1: 516 temp |= AMDTEMP_TTSR_SELSENSOR; 517 /* FALLTHROUGH */ 518 case CORE1_SENSOR0: 519 case CORE1: 520 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) == 0) 521 temp |= AMDTEMP_TTSR_SELCORE; 522 break; 523 } 524 pci_write_config(dev, AMDTEMP_THERMTP_STAT, temp, 1); 525 526 mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc; 527 offset = (sc->sc_flags & AMDTEMP_FLAG_ALT_OFFSET) != 0 ? 28 : 49; 528 temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4); 529 temp = ((temp >> 14) & mask) * 5 / 2; 530 temp += AMDTEMP_ZERO_C_TO_K + (sc->sc_offset - offset) * 10; 531 532 return (temp); 533} 534 535static int32_t 536amdtemp_gettemp(device_t dev, amdsensor_t sensor) 537{ 538 struct amdtemp_softc *sc = device_get_softc(dev); 539 uint32_t temp; 540 541 temp = pci_read_config(dev, AMDTEMP_REPTMP_CTRL, 4); 542 temp = ((temp >> 21) & 0x7ff) * 5 / 4; 543 temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10; 544 545 return (temp); 546}
| 191 family = CPUID_TO_FAMILY(cpu_id); 192 model = CPUID_TO_MODEL(cpu_id); 193 194 switch (family) { 195 case 0x0f: 196 if ((model == 0x04 && (cpu_id & CPUID_STEPPING) == 0) || 197 (model == 0x05 && (cpu_id & CPUID_STEPPING) <= 1)) 198 return (ENXIO); 199 break; 200 case 0x10: 201 case 0x11: 202 case 0x12: 203 case 0x14: 204 case 0x15: 205 break; 206 default: 207 return (ENXIO); 208 } 209 device_set_desc(dev, "AMD CPU On-Die Thermal Sensors"); 210 211 return (BUS_PROBE_GENERIC); 212} 213 214static int 215amdtemp_attach(device_t dev) 216{ 217 char tn[32]; 218 u_int regs[4]; 219 struct amdtemp_softc *sc = device_get_softc(dev); 220 struct sysctl_ctx_list *sysctlctx; 221 struct sysctl_oid *sysctlnode; 222 uint32_t cpuid, family, model; 223 u_int bid; 224 int erratum319, unit; 225 226 erratum319 = 0; 227 228 /* 229 * CPUID Register is available from Revision F. 230 */ 231 cpuid = cpu_id; 232 family = CPUID_TO_FAMILY(cpuid); 233 model = CPUID_TO_MODEL(cpuid); 234 if (family != 0x0f || model >= 0x40) { 235 cpuid = pci_read_config(dev, AMDTEMP_CPUID, 4); 236 family = CPUID_TO_FAMILY(cpuid); 237 model = CPUID_TO_MODEL(cpuid); 238 } 239 240 switch (family) { 241 case 0x0f: 242 /* 243 * Thermaltrip Status Register 244 * 245 * - ThermSenseCoreSel 246 * 247 * Revision F & G: 0 - Core1, 1 - Core0 248 * Other: 0 - Core0, 1 - Core1 249 * 250 * - CurTmp 251 * 252 * Revision G: bits 23-14 253 * Other: bits 23-16 254 * 255 * XXX According to the BKDG, CurTmp, ThermSenseSel and 256 * ThermSenseCoreSel bits were introduced in Revision F 257 * but CurTmp seems working fine as early as Revision C. 258 * However, it is not clear whether ThermSenseSel and/or 259 * ThermSenseCoreSel work in undocumented cases as well. 260 * In fact, the Linux driver suggests it may not work but 261 * we just assume it does until we find otherwise. 262 * 263 * XXX According to Linux, CurTmp starts at -28C on 264 * Socket AM2 Revision G processors, which is not 265 * documented anywhere. 266 */ 267 if (model >= 0x40) 268 sc->sc_flags |= AMDTEMP_FLAG_CS_SWAP; 269 if (model >= 0x60 && model != 0xc1) { 270 do_cpuid(0x80000001, regs); 271 bid = (regs[1] >> 9) & 0x1f; 272 switch (model) { 273 case 0x68: /* Socket S1g1 */ 274 case 0x6c: 275 case 0x7c: 276 break; 277 case 0x6b: /* Socket AM2 and ASB1 (2 cores) */ 278 if (bid != 0x0b && bid != 0x0c) 279 sc->sc_flags |= 280 AMDTEMP_FLAG_ALT_OFFSET; 281 break; 282 case 0x6f: /* Socket AM2 and ASB1 (1 core) */ 283 case 0x7f: 284 if (bid != 0x07 && bid != 0x09 && 285 bid != 0x0c) 286 sc->sc_flags |= 287 AMDTEMP_FLAG_ALT_OFFSET; 288 break; 289 default: 290 sc->sc_flags |= AMDTEMP_FLAG_ALT_OFFSET; 291 } 292 sc->sc_flags |= AMDTEMP_FLAG_CT_10BIT; 293 } 294 295 /* 296 * There are two sensors per core. 297 */ 298 sc->sc_ntemps = 2; 299 300 sc->sc_gettemp = amdtemp_gettemp0f; 301 break; 302 case 0x10: 303 /* 304 * Erratum 319 Inaccurate Temperature Measurement 305 * 306 * http://support.amd.com/us/Processor_TechDocs/41322.pdf 307 */ 308 do_cpuid(0x80000001, regs); 309 switch ((regs[1] >> 28) & 0xf) { 310 case 0: /* Socket F */ 311 erratum319 = 1; 312 break; 313 case 1: /* Socket AM2+ or AM3 */ 314 if ((pci_cfgregread(pci_get_bus(dev), 315 pci_get_slot(dev), 2, AMDTEMP_DRAM_CONF_HIGH, 2) & 316 AMDTEMP_DRAM_MODE_DDR3) != 0 || model > 0x04 || 317 (model == 0x04 && (cpuid & CPUID_STEPPING) >= 3)) 318 break; 319 /* XXX 00100F42h (RB-C2) exists in both formats. */ 320 erratum319 = 1; 321 break; 322 } 323 /* FALLTHROUGH */ 324 case 0x11: 325 case 0x12: 326 case 0x14: 327 case 0x15: 328 /* 329 * There is only one sensor per package. 330 */ 331 sc->sc_ntemps = 1; 332 333 sc->sc_gettemp = amdtemp_gettemp; 334 break; 335 } 336 337 /* Find number of cores per package. */ 338 sc->sc_ncores = (amd_feature2 & AMDID2_CMP) != 0 ? 339 (cpu_procinfo2 & AMDID_CMP_CORES) + 1 : 1; 340 if (sc->sc_ncores > MAXCPU) 341 return (ENXIO); 342 343 if (erratum319) 344 device_printf(dev, 345 "Erratum 319: temperature measurement may be inaccurate\n"); 346 if (bootverbose) 347 device_printf(dev, "Found %d cores and %d sensors.\n", 348 sc->sc_ncores, 349 sc->sc_ntemps > 1 ? sc->sc_ntemps * sc->sc_ncores : 1); 350 351 /* 352 * dev.amdtemp.N tree. 353 */ 354 unit = device_get_unit(dev); 355 snprintf(tn, sizeof(tn), "dev.amdtemp.%d.sensor_offset", unit); 356 TUNABLE_INT_FETCH(tn, &sc->sc_offset); 357 358 sysctlctx = device_get_sysctl_ctx(dev); 359 SYSCTL_ADD_INT(sysctlctx, 360 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 361 "sensor_offset", CTLFLAG_RW, &sc->sc_offset, 0, 362 "Temperature sensor offset"); 363 sysctlnode = SYSCTL_ADD_NODE(sysctlctx, 364 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 365 "core0", CTLFLAG_RD, 0, "Core 0"); 366 367 SYSCTL_ADD_PROC(sysctlctx, 368 SYSCTL_CHILDREN(sysctlnode), 369 OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD, 370 dev, CORE0_SENSOR0, amdtemp_sysctl, "IK", 371 "Core 0 / Sensor 0 temperature"); 372 373 if (sc->sc_ntemps > 1) { 374 SYSCTL_ADD_PROC(sysctlctx, 375 SYSCTL_CHILDREN(sysctlnode), 376 OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD, 377 dev, CORE0_SENSOR1, amdtemp_sysctl, "IK", 378 "Core 0 / Sensor 1 temperature"); 379 380 if (sc->sc_ncores > 1) { 381 sysctlnode = SYSCTL_ADD_NODE(sysctlctx, 382 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 383 OID_AUTO, "core1", CTLFLAG_RD, 0, "Core 1"); 384 385 SYSCTL_ADD_PROC(sysctlctx, 386 SYSCTL_CHILDREN(sysctlnode), 387 OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD, 388 dev, CORE1_SENSOR0, amdtemp_sysctl, "IK", 389 "Core 1 / Sensor 0 temperature"); 390 391 SYSCTL_ADD_PROC(sysctlctx, 392 SYSCTL_CHILDREN(sysctlnode), 393 OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD, 394 dev, CORE1_SENSOR1, amdtemp_sysctl, "IK", 395 "Core 1 / Sensor 1 temperature"); 396 } 397 } 398 399 /* 400 * Try to create dev.cpu sysctl entries and setup intrhook function. 401 * This is needed because the cpu driver may be loaded late on boot, 402 * after us. 403 */ 404 amdtemp_intrhook(dev); 405 sc->sc_ich.ich_func = amdtemp_intrhook; 406 sc->sc_ich.ich_arg = dev; 407 if (config_intrhook_establish(&sc->sc_ich) != 0) { 408 device_printf(dev, "config_intrhook_establish failed!\n"); 409 return (ENXIO); 410 } 411 412 return (0); 413} 414 415void 416amdtemp_intrhook(void *arg) 417{ 418 struct amdtemp_softc *sc; 419 struct sysctl_ctx_list *sysctlctx; 420 device_t dev = (device_t)arg; 421 device_t acpi, cpu, nexus; 422 amdsensor_t sensor; 423 int i; 424 425 sc = device_get_softc(dev); 426 427 /* 428 * dev.cpu.N.temperature. 429 */ 430 nexus = device_find_child(root_bus, "nexus", 0); 431 acpi = device_find_child(nexus, "acpi", 0); 432 433 for (i = 0; i < sc->sc_ncores; i++) { 434 if (sc->sc_sysctl_cpu[i] != NULL) 435 continue; 436 cpu = device_find_child(acpi, "cpu", 437 device_get_unit(dev) * sc->sc_ncores + i); 438 if (cpu != NULL) { 439 sysctlctx = device_get_sysctl_ctx(cpu); 440 441 sensor = sc->sc_ntemps > 1 ? 442 (i == 0 ? CORE0 : CORE1) : CORE0_SENSOR0; 443 sc->sc_sysctl_cpu[i] = SYSCTL_ADD_PROC(sysctlctx, 444 SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), 445 OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, 446 dev, sensor, amdtemp_sysctl, "IK", 447 "Current temparature"); 448 } 449 } 450 if (sc->sc_ich.ich_arg != NULL) 451 config_intrhook_disestablish(&sc->sc_ich); 452} 453 454int 455amdtemp_detach(device_t dev) 456{ 457 struct amdtemp_softc *sc = device_get_softc(dev); 458 int i; 459 460 for (i = 0; i < sc->sc_ncores; i++) 461 if (sc->sc_sysctl_cpu[i] != NULL) 462 sysctl_remove_oid(sc->sc_sysctl_cpu[i], 1, 0); 463 464 /* NewBus removes the dev.amdtemp.N tree by itself. */ 465 466 return (0); 467} 468 469static int 470amdtemp_sysctl(SYSCTL_HANDLER_ARGS) 471{ 472 device_t dev = (device_t)arg1; 473 struct amdtemp_softc *sc = device_get_softc(dev); 474 amdsensor_t sensor = (amdsensor_t)arg2; 475 int32_t auxtemp[2], temp; 476 int error; 477 478 switch (sensor) { 479 case CORE0: 480 auxtemp[0] = sc->sc_gettemp(dev, CORE0_SENSOR0); 481 auxtemp[1] = sc->sc_gettemp(dev, CORE0_SENSOR1); 482 temp = imax(auxtemp[0], auxtemp[1]); 483 break; 484 case CORE1: 485 auxtemp[0] = sc->sc_gettemp(dev, CORE1_SENSOR0); 486 auxtemp[1] = sc->sc_gettemp(dev, CORE1_SENSOR1); 487 temp = imax(auxtemp[0], auxtemp[1]); 488 break; 489 default: 490 temp = sc->sc_gettemp(dev, sensor); 491 break; 492 } 493 error = sysctl_handle_int(oidp, &temp, 0, req); 494 495 return (error); 496} 497 498#define AMDTEMP_ZERO_C_TO_K 2732 499 500static int32_t 501amdtemp_gettemp0f(device_t dev, amdsensor_t sensor) 502{ 503 struct amdtemp_softc *sc = device_get_softc(dev); 504 uint32_t mask, offset, temp; 505 506 /* Set Sensor/Core selector. */ 507 temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 1); 508 temp &= ~(AMDTEMP_TTSR_SELCORE | AMDTEMP_TTSR_SELSENSOR); 509 switch (sensor) { 510 case CORE0_SENSOR1: 511 temp |= AMDTEMP_TTSR_SELSENSOR; 512 /* FALLTHROUGH */ 513 case CORE0_SENSOR0: 514 case CORE0: 515 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) != 0) 516 temp |= AMDTEMP_TTSR_SELCORE; 517 break; 518 case CORE1_SENSOR1: 519 temp |= AMDTEMP_TTSR_SELSENSOR; 520 /* FALLTHROUGH */ 521 case CORE1_SENSOR0: 522 case CORE1: 523 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) == 0) 524 temp |= AMDTEMP_TTSR_SELCORE; 525 break; 526 } 527 pci_write_config(dev, AMDTEMP_THERMTP_STAT, temp, 1); 528 529 mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc; 530 offset = (sc->sc_flags & AMDTEMP_FLAG_ALT_OFFSET) != 0 ? 28 : 49; 531 temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4); 532 temp = ((temp >> 14) & mask) * 5 / 2; 533 temp += AMDTEMP_ZERO_C_TO_K + (sc->sc_offset - offset) * 10; 534 535 return (temp); 536} 537 538static int32_t 539amdtemp_gettemp(device_t dev, amdsensor_t sensor) 540{ 541 struct amdtemp_softc *sc = device_get_softc(dev); 542 uint32_t temp; 543 544 temp = pci_read_config(dev, AMDTEMP_REPTMP_CTRL, 4); 545 temp = ((temp >> 21) & 0x7ff) * 5 / 4; 546 temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10; 547 548 return (temp); 549}
|