Date: Mon, 7 Oct 2013 05:24:41 +0400 From: rozhuk.im@gmail.com To: <hackers@freebsd.org> Subject: amdtemp need help with testing Message-ID: <52520d5f.c402cd0a.5f4e.ffffffa2@mx.google.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. ------=_NextPart_000_0206_01CEC31D.875A19E0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit I updated amdtemp and now I need your help with testing. Now the driver should support all AMD processors. For a family of 15h and 16h, not all sensors are available - for my system does not find drivers for ati SMBus, and other systems based on the AMD I have not. ------=_NextPart_000_0206_01CEC31D.875A19E0 Content-Type: text/plain; name="amdtemp.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="amdtemp.c" /*-=0A= * Copyright (c) 2008, 2009 Rui Paulo <rpaulo@FreeBSD.org>=0A= * Copyright (c) 2009 Norikatsu Shigemura <nork@FreeBSD.org>=0A= * Copyright (c) 2009-2011 Jung-uk Kim <jkim@FreeBSD.org>=0A= * Copyright (c) 2013 Rozhuk Ivan <rozhuk.im@gmail.com>=0A= * All rights reserved.=0A= *=0A= * Redistribution and use in source and binary forms, with or without=0A= * modification, are permitted provided that the following conditions=0A= * are met:=0A= * 1. Redistributions of source code must retain the above copyright=0A= * notice, this list of conditions and the following disclaimer.=0A= * 2. Redistributions in binary form must reproduce the above copyright=0A= * notice, this list of conditions and the following disclaimer in the=0A= * documentation and/or other materials provided with the = distribution.=0A= *=0A= * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR=0A= * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED=0A= * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE=0A= * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,=0A= * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES=0A= * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR=0A= * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)=0A= * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,=0A= * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING = IN=0A= * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE=0A= * POSSIBILITY OF SUCH DAMAGE.=0A= */=0A= =0A= /*=0A= * Driver for the AMD CPU on-die thermal sensors.=0A= * Initially based on the k8temp Linux driver.=0A= */=0A= =0A= #include <sys/cdefs.h>=0A= __FBSDID("$FreeBSD$");=0A= =0A= #include <sys/param.h>=0A= #include <sys/systm.h>=0A= #include <sys/kernel.h>=0A= #include <sys/module.h>=0A= #include <sys/bus.h>=0A= #include <sys/resource.h>=0A= #include <sys/rman.h>=0A= #include <sys/sysctl.h>=0A= #include <sys/lock.h>=0A= #include <sys/mutex.h>=0A= =0A= #include <machine/bus.h>=0A= #include <machine/resource.h>=0A= #include <machine/md_var.h>=0A= #include <machine/specialreg.h>=0A= #include <machine/cputypes.h>=0A= =0A= #include <dev/pci/pcivar.h>=0A= =0A= #if defined(__FreeBSD_version) && (__FreeBSD_version < 999999)=0A= /* XXX */=0A= extern uint32_t pci_cfgregread(int, int, int, int, int);=0A= #endif=0A= =0A= =0A= struct amdtemp_softc {=0A= device_t dev;=0A= struct mtx lock; /* Read/write lock for some registers. */=0A= uint32_t cpu_ncores;=0A= uint32_t flags;=0A= uint32_t tts_flags; /* Thermaltrip Status flags. */=0A= int32_t tts_temp_offset[4];=0A= int32_t rtc_temp_offset;=0A= int32_t tsi_temp_offset[8];=0A= struct sysctl_oid *sysctl_cpu[MAXCPU]; /* dev.cpu.X.temperature oids. */=0A= struct intr_config_hook sc_ich;=0A= };=0A= #define AMDTEMP_F_TTS 1 /* Thermaltrip Status. */=0A= #define AMDTEMP_F_RTC 2 /* Reported Temperature Control. */=0A= #define AMDTEMP_F_TSI 4 /* TSI via CPU registers. */=0A= #define AMDTEMP_F_SBTSI 8 /* TSI via SMBus. */=0A= =0A= #define AMDTEMP_TTS_F_CS_SWAP 0x01 /* ThermSenseCoreSel is inverted. */=0A= #define AMDTEMP_TTS_F_CT_10BIT 0x02 /* CurTmp is 10-bit wide. */=0A= #define AMDTEMP_TTS_F_OFF28 0x04 /* CurTmp starts at -28C. */=0A= =0A= =0A= #define AMDTEMP_LOCK(sc) mtx_lock(&(sc)->lock)=0A= #define AMDTEMP_UNLOCK(sc) mtx_unlock(&(sc)->lock)=0A= =0A= =0A= /* CPU Family/Model Register */=0A= #define AMD_REG_CPUID 0xfc=0A= =0A= /* =0A= * Thermaltrip Status Register=0A= * BIOS and Kernel Developer=E2=80=99s Guide for AMD NPT Family 0Fh = Processors=0A= * 32559 Rev. 3.16 November 2009=0A= */=0A= /* D18F3xE4 Thermtrip Status Register */=0A= #define AMD_REG_THERMTRIP_STAT 0xe4=0A= union reg_amd_thermtrip_status_desc {=0A= uint32_t u32;=0A= struct reg_amd_thermtrip_status_bits {=0A= uint32_t r0:1; /* 0 Reserved. */=0A= uint32_t Thermtp:1; /* 1 ro The processor has entered the THERMTRIP = state. */=0A= uint32_t ThermSenseCoreSel:1; /* 2 rw */=0A= uint32_t ThermtpSense0:1; /* 3 ro */=0A= uint32_t ThermtpSense1:1; /* 4 ro */=0A= uint32_t ThermtpEn:1; /* 5 ro The THERMTRIP state is supported by the = processor. */=0A= uint32_t ThermSenseSel:1; /* 6 rw */=0A= uint32_t r1:1; /* 7 Reserved. */=0A= uint32_t DiodeOffset:6; /* 13:8 ro Thermal diode offset is used to = correct the measurement made by an external temperature sensor. */=0A= uint32_t CurTmp:10; /* 23:14 ro This field returns the current value = of the internal thermal sensor. */=0A= uint32_t TjOffset:5; /* 28:24 ro This field is the offset from CurTmp = used to normalize to Tcontrol. */=0A= uint32_t r2:2; /* 30:29 Reserved. */=0A= uint32_t SwThermtp:1; /* 31 rw */=0A= } __packed bits;=0A= };=0A= =0A= =0A= /* DRAM Configuration High Register */=0A= #define AMD_REG_DRAM_CONF_HIGH 0x94 /* Function 2 */=0A= #define AMD_REG_DRAM_MODE_DDR3 0x0100=0A= =0A= /* D18F3xA4 Reported Temperature Control Register */=0A= #define AMD_REG_REPTMP_CTRL 0xa4=0A= union reg_amd_rep_tmp_ctrl_desc {=0A= uint32_t u32;=0A= struct reg_amd_rep_tmp_ctrl_bits {=0A= uint32_t PerStepTimeUp:5; /* 4:0 rw per 1/8th step time up. */=0A= uint32_t TmpMaxDiffUp:2;/* 6:5 rw temperature maximum difference up. */=0A= uint32_t TmpSlewDnEn:1; /* 7 rw temperature slew downward enable. */=0A= uint32_t PerStepTimeDn:5;/* 12:8 rw per 1/8th step time down. */=0A= uint32_t r0:3; /* 15:13 Reserved. */=0A= uint32_t CurTmpTjSel:2; /* 17:16 rw Current temperature select. */=0A= uint32_t r1:3; /* 20:18 Reserved. */=0A= uint32_t CurTmp:11; /* 31:21 ro/rw current temperature. */=0A= } __packed bits;=0A= };=0A= /* CurTmpTjSel valid family 10h, 15h, 16h processors. */=0A= =0A= =0A= /* SB-TSI */=0A= #define AMD_REG_SBI_CTRL 0x1e4 /* SBI Control */=0A= union reg_amd_sbi_ctrl_desc {=0A= uint32_t u32;=0A= struct reg_amd_sbi_ctrl_bits {=0A= uint32_t r0:1; /* 0 Reserved. */=0A= uint32_t SbRmiDis:1; /* 1 ro SMBus-based sideband remote management = interface disable. */=0A= uint32_t r1:1; /* 2 Reserved. */=0A= uint32_t SbTsiDis:1; /* 3 ro SMBus-based sideband temperature sensor = interface disable. */=0A= uint32_t SbiAddr:3; /* 6:4 rw SMBus-based sideband interface address. = */=0A= uint32_t r2:1; /* 7 Reserved. */=0A= uint32_t LvtOffset:4; /* 11:8 rw local vector table offset. */=0A= uint32_t r3:19; /* 30:12 Reserved. */=0A= uint32_t SbiRegWrDn:1; /* 31 ro SBI register write complete. */=0A= } __packed bits;=0A= };=0A= /*=0A= * AMD Family 10h Processor BKDG: SbRmiDis (bit offset: 1) + SbTsiDis = (bit offset: 3)=0A= * AMD Family 11h Processor BKDG: SbTsiDis (bit offset: 1)=0A= * AMD Family 12h Processor BKDG: SbTsiDis (bit offset: 1)=0A= * BKDG for AMD Family 14h Models 00h-0Fh Processors: SbTsiDis (bit = offset: 1)=0A= * BKDG for AMD Family 15h Models 00h-0Fh Processors: SbRmiDis, no TSI=0A= * BKDG for AMD Family 16h Models 00h-0Fh Processors: ??? 48751 Rev 3.00 = - May 30, 2013=0A= */=0A= #define AMD_REG_SBI_ADDR 0x1e8 /* SBI Address */=0A= #define AMD_REG_SBI_ADDR_MASK 0x07=0A= #define AMD_REG_SBI_DATA 0x1ec /* SBI Data */=0A= #define AMD_SBI_WRITE_TIMEOUT 100 /* XXX should be increased? */=0A= =0A= /* SB-TSI registers. */=0A= #define SB_TSI_REG_CPU_TEMP_HB 0x01 /* CPU Temperature High Byte = Register. */=0A= #define SB_TSI_REG_STATUS 0x02 /* SB-TSI Status Register. */=0A= #define SB_TSI_REG_CFG 0x03 /* SB-TSI Configuration Register. */=0A= #define SB_TSI_REG_UPD_RATE 0x04 /* Update Rate Register. */=0A= #define SB_TSI_REG_HIGH_TEMP_THB 0x07 /* High Temperature Threshold High = Byte Register. */=0A= #define SB_TSI_REG_LOW_TEMP_THB 0x08 /* Low Temperature Threshold High = Byte Register.*/=0A= #define SB_TSI_REG_CFG2 0x09 /* SB-TSI Configuration Register. */=0A= #define SB_TSI_REG_CPU_TEMP_LB 0x10 /* CPU Temperature Low Byte = Register. */=0A= #define SB_TSI_REG_CPU_TEMP_OFF_HB 0x11 /* CPU Temperature Offset High = Byte Register. */=0A= #define SB_TSI_REG_CPU_TEMP_OFF_LB 0x12 /* CPU Temperature Offset Low = Byte Register. */=0A= #define SB_TSI_REG_HIGH_TEMP_TLB 0x13 /* High Temperature Threshold Low = Byte Register. */=0A= #define SB_TSI_REG_LOW_TEMP_TLB 0x14 /* Low Temperature Threshold Low = Byte Register. */=0A= #define SB_TSI_REG_TIMEOUT_CFG 0x22 /* Timeout Configuration Register. = */=0A= #define SB_TSI_REG_ALERT_THRESHOLD 0x32 /* Alert Threshold Register. */=0A= #define SB_TSI_REG_ALERT_CFG 0xbf /* Alert Configuration Register. */=0A= #define SB_TSI_REG_MANUFACTURE_ID 0xfe /* Manufacture ID Register. */=0A= #define SB_TSI_REG_REVISION 0xff /* SB-TSI Revision Register. */=0A= =0A= =0A= =0A= #define AMDTEMP_ZERO_C_TO_K 2732=0A= =0A= =0A= #define ARG2_GET_REG(arg) ((arg) & 0xffff)=0A= #define ARG2_GET_A1(arg) (((arg) >> 16) & 0xff)=0A= #define ARG2_GET_A2(arg) (((arg) >> 24) & 0xff)=0A= #define MAKE_ARG2(reg, a1, a2) \=0A= (((reg) & 0xff) | (((a1) & 0xff) << 16) | (((a2) & 0xff) << 24))=0A= =0A= struct amdtemp_sysctl_reg {=0A= uint16_t reg;=0A= uint8_t a1;=0A= uint8_t a2;=0A= uint32_t flags;=0A= char *fmt;=0A= int (*oid_handler)(SYSCTL_HANDLER_ARGS);=0A= char *name;=0A= char *descr;=0A= };=0A= =0A= static void amdtemp_sysctl_reg_add(struct amdtemp_softc *sc,=0A= struct sysctl_oid_list *child, struct amdtemp_sysctl_reg *regs);=0A= static void amdtemp_sysctl_reg_add2(struct amdtemp_softc *sc,=0A= struct sysctl_oid_list *child, struct amdtemp_sysctl_reg *regs,=0A= uint32_t a2);=0A= static int amdtemp_sysctl_reg_bits(SYSCTL_HANDLER_ARGS);=0A= =0A= static uint32_t amdtemp_tts_get_temp(struct amdtemp_softc *sc, uint32_t = reg,=0A= uint8_t core, uint8_t sense);=0A= static int amdtemp_tts_temp_reg_sysctl(SYSCTL_HANDLER_ARGS);=0A= =0A= static int amdtemp_rtc_temp_sysctl(SYSCTL_HANDLER_ARGS);=0A= =0A= static void amdtemp_sbi_set_addr(struct amdtemp_softc *sc, uint32_t = sbi_addr);=0A= static uint32_t amdtemp_sbi_read(struct amdtemp_softc *sc, uint32_t = sbi_addr,=0A= uint32_t reg_addr);=0A= static int amdtemp_sbi_write(struct amdtemp_softc *sc, uint32_t sbi_addr,=0A= uint32_t reg_addr, uint8_t data);=0A= static int amdtemp_tsi_reg_sysctl(SYSCTL_HANDLER_ARGS);=0A= static int amdtemp_tsi_temp_reg_sysctl(SYSCTL_HANDLER_ARGS);=0A= =0A= =0A= /* D18F3xE4 Thermtrip Status Register */=0A= static struct amdtemp_sysctl_reg amdtemp_thermtrip_status_reg_bits[] =3D = {=0A= { AMD_REG_THERMTRIP_STAT, 24, 5, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "TjOffset", "This field is the offset from = CurTmp used to normalize to Tcontrol." },=0A= { AMD_REG_THERMTRIP_STAT, 8, 6, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "DiodeOffset", "Thermal diode offset is used to = correct the measurement made by an external temperature sensor." },=0A= { AMD_REG_THERMTRIP_STAT, 5, 1, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "ThermtpEn", "The THERMTRIP state is supported = by the processor." },=0A= { AMD_REG_THERMTRIP_STAT, 1, 1, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "Thermtrip", "The processor has entered the = THERMTRIP state." },=0A= =0A= { 0, 0, 0, 0, NULL, NULL, NULL, NULL }=0A= };=0A= =0A= /* D18F3xA4 Reported Temperature Control Register */=0A= static struct amdtemp_sysctl_reg amdtemp_reptmp_reg_bits[] =3D {=0A= { AMD_REG_REPTMP_CTRL, 21,11, (CTLFLAG_RD | CTLTYPE_INT), "IK", = amdtemp_rtc_temp_sysctl, "CurTmp", "Provides the current control = temperature, Tctl, after the slew-rate controls have been applied." },=0A= { AMD_REG_REPTMP_CTRL, 16, 2, (CTLFLAG_RW | CTLTYPE_INT), "IK", = amdtemp_rtc_temp_sysctl, "CurTmpTjSel", "Specifies a value used to = create Tctl." },=0A= { AMD_REG_REPTMP_CTRL, 7, 1, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "TmpSlewDnEn", "Temperature slew downward = enable." },=0A= { AMD_REG_REPTMP_CTRL, 5, 2, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "TmpMaxDiffUp", "Specifies the maximum = difference, (Tctlm - Tctl), when Tctl immediatly updates to Tctlm." },=0A= { AMD_REG_REPTMP_CTRL, 8, 5, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "PerStepTimeDn", "Specifies the time that Tctlm = must remain below Tctl before applying a 0.125 downward step." },=0A= { AMD_REG_REPTMP_CTRL, 0, 5, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_sysctl_reg_bits, "PerStepTimeUp", "Specifies the time that Tctlm = must remain above Tctl before applying a 0.125 upward step." },=0A= =0A= { 0, 0, 0, 0, NULL, NULL, NULL, NULL }=0A= };=0A= =0A= /* SB-TSI registers. */=0A= static struct amdtemp_sysctl_reg amdtemp_tsi_regs[] =3D {=0A= { SB_TSI_REG_CPU_TEMP_LB, SB_TSI_REG_CPU_TEMP_HB, 0, (CTLFLAG_RD | = CTLTYPE_INT), "IK", amdtemp_tsi_temp_reg_sysctl, "cpu_temperature", "CPU = Temperature" },=0A= { SB_TSI_REG_HIGH_TEMP_TLB, SB_TSI_REG_HIGH_TEMP_THB, 0, (CTLFLAG_RD | = CTLTYPE_INT), "IK", amdtemp_tsi_temp_reg_sysctl, = "high_temperature_threshold", "High Temperature Threshold" },=0A= { SB_TSI_REG_LOW_TEMP_TLB, SB_TSI_REG_LOW_TEMP_THB, 0, (CTLFLAG_RD | = CTLTYPE_INT), "IK", amdtemp_tsi_temp_reg_sysctl, = "low_temperature_threshold", "Low Temperature Threshold" },=0A= =0A= { SB_TSI_REG_CPU_TEMP_OFF_HB, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "cpu_temperature_offset_hi", "CPU Temperature = Offset High Byte" },=0A= { SB_TSI_REG_CPU_TEMP_OFF_LB, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "cpu_temperature_offset_lo", "CPU Temperature = Offset Low Byte" },=0A= =0A= { SB_TSI_REG_STATUS, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "status", "SB-TSI Status" },=0A= { SB_TSI_REG_CFG, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "cfg3", "SB-TSI Configuration Register 0x03" },=0A= { SB_TSI_REG_CFG2, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "cfg9", "SB-TSI Configuration Register 0x09" },=0A= { SB_TSI_REG_UPD_RATE, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "upd_rate", "Update Rate" },=0A= { SB_TSI_REG_TIMEOUT_CFG, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "timeout_cfg", "Timeout Configuration" },=0A= { SB_TSI_REG_ALERT_THRESHOLD, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "alert_threshold", "Alert Threshold" },=0A= { SB_TSI_REG_ALERT_CFG, 0, 0, (CTLFLAG_RW | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "alert_cfg", "Alert Configuration" },=0A= { SB_TSI_REG_MANUFACTURE_ID, 0, 0, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "manufacture_id", "Manufacture ID" },=0A= { SB_TSI_REG_REVISION, 0, 0, (CTLFLAG_RD | CTLTYPE_UINT), "IU", = amdtemp_tsi_reg_sysctl, "revision", "SB-TSI Revision" },=0A= =0A= { 0, 0, 0, 0, NULL, NULL, NULL, NULL }=0A= };=0A= =0A= =0A= /*=0A= * Device methods.=0A= */=0A= static void amdtemp_identify(driver_t *driver, device_t parent);=0A= static int amdtemp_probe(device_t dev);=0A= static int amdtemp_attach(device_t dev);=0A= static int amdtemp_detach(device_t dev);=0A= static void amdtemp_intrhook(void *arg);=0A= =0A= =0A= static device_method_t amdtemp_methods[] =3D {=0A= /* Device interface */=0A= DEVMETHOD(device_identify, amdtemp_identify),=0A= DEVMETHOD(device_probe, amdtemp_probe),=0A= DEVMETHOD(device_attach, amdtemp_attach),=0A= DEVMETHOD(device_detach, amdtemp_detach),=0A= =0A= DEVMETHOD_END=0A= };=0A= =0A= static driver_t amdtemp_driver =3D {=0A= "amdtemp",=0A= amdtemp_methods,=0A= sizeof(struct amdtemp_softc),=0A= };=0A= static devclass_t amdtemp_devclass;=0A= DRIVER_MODULE(amdtemp, hostb, amdtemp_driver, amdtemp_devclass, NULL, = NULL);=0A= MODULE_VERSION(amdtemp, 1);=0A= =0A= =0A= =0A= static void=0A= amdtemp_identify(driver_t *driver, device_t parent) {=0A= device_t child;=0A= uint32_t cpuid, model;=0A= =0A= /* Make sure we're not being doubly invoked. */=0A= if (device_find_child(parent, "amdtemp", -1) !=3D NULL)=0A= return;=0A= /* AMD processors only. */=0A= if (CPU_VENDOR_AMD !=3D pci_get_vendor(parent))=0A= return;=0A= /* Is processor supported? */=0A= cpuid =3D pci_read_config(parent, AMD_REG_CPUID, 4);=0A= switch (CPUID_TO_FAMILY(cpuid)) {=0A= case 0x0f:=0A= model =3D CPUID_TO_MODEL(cpuid);=0A= if ((model =3D=3D 0x04 && (cpuid & CPUID_STEPPING) =3D=3D 0) ||=0A= (model =3D=3D 0x05 && (cpuid & CPUID_STEPPING) <=3D 1))=0A= return;=0A= break;=0A= case 0x10:=0A= case 0x11:=0A= case 0x12:=0A= case 0x14:=0A= case 0x15:=0A= case 0x16:=0A= break;=0A= default:=0A= return;=0A= }=0A= /* Ok! */=0A= child =3D device_add_child(parent, "amdtemp", -1);=0A= if (child =3D=3D NULL)=0A= device_printf(parent, "add amdtemp child failed\n");=0A= }=0A= =0A= static int=0A= amdtemp_probe(device_t dev) {=0A= =0A= if (resource_disabled("amdtemp", 0))=0A= return (ENXIO);=0A= =0A= device_set_desc(dev, "AMD CPU On-Die Thermal Sensors");=0A= =0A= return (BUS_PROBE_GENERIC);=0A= }=0A= =0A= static int=0A= amdtemp_attach(device_t dev) {=0A= struct amdtemp_softc *sc =3D device_get_softc(dev);=0A= uint32_t i, cpuid, model;=0A= union reg_amd_sbi_ctrl_desc reg_ctrl;=0A= struct sysctl_ctx_list *ctx =3D device_get_sysctl_ctx(dev);=0A= struct sysctl_oid_list *child =3D = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), *list;=0A= struct sysctl_oid *node, *sub_node;=0A= char str[32];=0A= int erratum319 =3D 0;=0A= u_int regs[4], bid;=0A= =0A= sc->dev =3D dev;=0A= /* Find number of cores per package. */=0A= sc->cpu_ncores =3D (((amd_feature2 & AMDID2_CMP) !=3D 0) ?=0A= ((cpu_procinfo2 & AMDID_CMP_CORES) + 1) : 1);=0A= if (sc->cpu_ncores > MAXCPU)=0A= return (ENXIO);=0A= mtx_init(&sc->lock, device_get_nameunit(dev), "amdtemp", MTX_DEF);=0A= =0A= cpuid =3D pci_read_config(dev, AMD_REG_CPUID, 4);=0A= model =3D CPUID_TO_MODEL(cpuid);=0A= switch (CPUID_TO_FAMILY(cpuid)) {=0A= case 0x0f:=0A= /*=0A= * Thermaltrip Status Register=0A= *=0A= * - ThermSenseCoreSel=0A= *=0A= * Revision F & G: 0 - Core1, 1 - Core0=0A= * Other: 0 - Core0, 1 - Core1=0A= *=0A= * - CurTmp=0A= *=0A= * Revision G: bits 23-14=0A= * Other: bits 23-16=0A= *=0A= * XXX According to the BKDG, CurTmp, ThermSenseSel and=0A= * ThermSenseCoreSel bits were introduced in Revision F=0A= * but CurTmp seems working fine as early as Revision C.=0A= * However, it is not clear whether ThermSenseSel and/or=0A= * ThermSenseCoreSel work in undocumented cases as well.=0A= * In fact, the Linux driver suggests it may not work but=0A= * we just assume it does until we find otherwise.=0A= *=0A= * XXX According to Linux, CurTmp starts at -28C on=0A= * Socket AM2 Revision G processors, which is not=0A= * documented anywhere.=0A= * XXX check TjOffset and DiodeOffset for -49C / -28C=0A= */=0A= if ((model =3D=3D 0x04 && (cpuid & CPUID_STEPPING) =3D=3D 0) ||=0A= (model =3D=3D 0x05 && (cpuid & CPUID_STEPPING) <=3D 1))=0A= break; /* No ThermalTrip. */=0A= sc->flags |=3D AMDTEMP_F_TTS;=0A= if (model >=3D 0x40)=0A= sc->tts_flags |=3D AMDTEMP_TTS_F_CS_SWAP;=0A= if (model >=3D 0x60 && model !=3D 0xc1) {=0A= do_cpuid(0x80000001, regs);=0A= bid =3D (regs[1] >> 9) & 0x1f;=0A= switch (model) {=0A= case 0x68: /* Socket S1g1 */=0A= case 0x6c:=0A= case 0x7c:=0A= break;=0A= case 0x6b: /* Socket AM2 and ASB1 (2 cores) */=0A= if (bid !=3D 0x0b &&=0A= bid !=3D 0x0c)=0A= sc->tts_flags |=3D AMDTEMP_TTS_F_OFF28;=0A= break;=0A= case 0x6f: /* Socket AM2 and ASB1 (1 core) */=0A= case 0x7f:=0A= if (bid !=3D 0x07 &&=0A= bid !=3D 0x09 &&=0A= bid !=3D 0x0c)=0A= sc->tts_flags |=3D AMDTEMP_TTS_F_OFF28;=0A= break;=0A= default:=0A= sc->tts_flags |=3D AMDTEMP_TTS_F_OFF28;=0A= }=0A= sc->tts_flags |=3D AMDTEMP_TTS_F_CT_10BIT;=0A= }=0A= break;=0A= case 0x10:=0A= sc->flags |=3D AMDTEMP_F_RTC;=0A= reg_ctrl.u32 =3D pci_read_config(dev, AMD_REG_SBI_CTRL, 4);=0A= if (0 =3D=3D reg_ctrl.bits.SbTsiDis)=0A= sc->flags |=3D AMDTEMP_F_TSI;=0A= /*=0A= * Erratum 319 Inaccurate Temperature Measurement=0A= * http://support.amd.com/us/Processor_TechDocs/41322.pdf=0A= */=0A= do_cpuid(0x80000001, regs);=0A= switch ((regs[1] >> 28) & 0xf) {=0A= case 0: /* Socket F */=0A= erratum319 =3D 1;=0A= break;=0A= case 1: /* Socket AM2+ or AM3 */=0A= if ((pci_cfgregread(pci_get_bus(dev), pci_get_slot(dev), 2,=0A= AMD_REG_DRAM_CONF_HIGH, 2) & AMD_REG_DRAM_MODE_DDR3) !=3D 0 ||=0A= model > 0x04 ||=0A= (model =3D=3D 0x04 && (cpuid & CPUID_STEPPING) >=3D 3))=0A= break;=0A= /* XXX 00100F42h (RB-C2) exists in both formats. */=0A= erratum319 =3D 1;=0A= break;=0A= }=0A= break;=0A= case 0x11:=0A= case 0x12:=0A= case 0x14:=0A= sc->flags |=3D AMDTEMP_F_RTC;=0A= reg_ctrl.u32 =3D pci_read_config(dev, AMD_REG_SBI_CTRL, 4);=0A= if (0 =3D=3D reg_ctrl.bits.SbRmiDis) /* =3D SbTsiDis */=0A= sc->flags |=3D AMDTEMP_F_TSI;=0A= break;=0A= case 0x15:=0A= case 0x16:=0A= default:=0A= sc->flags |=3D AMDTEMP_F_RTC;=0A= /* XXX TODO: read TSI via SMBus. */=0A= break;=0A= }=0A= =0A= if (0 !=3D (sc->flags & AMDTEMP_F_TTS)) { /* Thermaltrip Status */=0A= node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "tts",=0A= CTLFLAG_RD, NULL, "Thermaltrip Status");=0A= list =3D SYSCTL_CHILDREN(node);=0A= amdtemp_sysctl_reg_add(sc, list, amdtemp_thermtrip_status_reg_bits);=0A= for (i =3D 0; i < sc->cpu_ncores && i < 2; i ++) {=0A= snprintf(str, sizeof(str), "core%i", i);=0A= sub_node =3D SYSCTL_ADD_NODE(ctx, list, OID_AUTO, str,=0A= CTLFLAG_RD, NULL, "CPU core sensors");=0A= SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sub_node), OID_AUTO,=0A= "sensor0", (CTLTYPE_INT | CTLFLAG_RD), sc,=0A= MAKE_ARG2(AMD_REG_THERMTRIP_STAT, i, 0),=0A= amdtemp_tts_temp_reg_sysctl, "IK", "Sensor 0 temperature");=0A= SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sub_node), OID_AUTO,=0A= "sensor1", (CTLTYPE_INT | CTLFLAG_RD), sc,=0A= MAKE_ARG2(AMD_REG_THERMTRIP_STAT, i, 1),=0A= amdtemp_tts_temp_reg_sysctl, "IK", "Sensor 1 temperature");=0A= SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(sub_node), OID_AUTO,=0A= "sensor0_offset", CTLFLAG_RW,=0A= &sc->tts_temp_offset[((i << 1) | 0)], 0,=0A= "Temperature sensor offset");=0A= SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(sub_node), OID_AUTO,=0A= "sensor1_offset", CTLFLAG_RW,=0A= &sc->tts_temp_offset[((i << 1) | 1)], 0,=0A= "Temperature sensor offset");=0A= }=0A= }=0A= if (0 !=3D (sc->flags & AMDTEMP_F_RTC)) { /* Reported Temperature = Control */=0A= node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "rtc",=0A= CTLFLAG_RD, NULL, "Reported Temperature Control");=0A= list =3D SYSCTL_CHILDREN(node);=0A= amdtemp_sysctl_reg_add(sc, list, amdtemp_reptmp_reg_bits);=0A= SYSCTL_ADD_INT(ctx, list, OID_AUTO, "sensor_offset", CTLFLAG_RW,=0A= &sc->rtc_temp_offset, 0, "Temperature sensor offset");=0A= }=0A= if (0 !=3D (sc->flags & AMDTEMP_F_TSI)) { /* Temperature Sensor = Interface */=0A= node =3D SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "tsi",=0A= CTLFLAG_RD, NULL, "Temperature Sensor Interface");=0A= list =3D SYSCTL_CHILDREN(node);=0A= for (i =3D 0; i < 8; i ++) {=0A= if (0 =3D=3D amdtemp_sbi_read(sc, i, SB_TSI_REG_REVISION))=0A= continue;=0A= snprintf(str, sizeof(str), "sensor%i", i);=0A= sub_node =3D SYSCTL_ADD_NODE(ctx, list, OID_AUTO, str,=0A= CTLFLAG_RD, NULL, "TSI sensor");=0A= amdtemp_sysctl_reg_add2(sc, SYSCTL_CHILDREN(sub_node),=0A= amdtemp_tsi_regs, i);=0A= SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(sub_node), OID_AUTO,=0A= "sensor_offset", CTLFLAG_RW, &sc->tsi_temp_offset[i], 0,=0A= "Temperature sensor offset");=0A= }=0A= }=0A= =0A= if (bootverbose) {=0A= if (0 !=3D (sc->flags & AMDTEMP_F_TTS))=0A= device_printf(dev, "Found: Thermaltrip Status.\n");=0A= if (0 !=3D (sc->flags & AMDTEMP_F_RTC))=0A= device_printf(dev, "Found: Reported Temperature Control.\n");=0A= if (0 !=3D (sc->flags & AMDTEMP_F_TSI))=0A= device_printf(dev, "Found: Temperature Sensor Interface via CPU = registers.\n");=0A= }=0A= if (erratum319)=0A= device_printf(dev,=0A= "Erratum 319: temperature measurement may be inaccurate\n");=0A= /*=0A= * Try to create dev.cpu sysctl entries and setup intrhook function.=0A= * This is needed because the cpu driver may be loaded late on boot,=0A= * after us.=0A= */=0A= amdtemp_intrhook(dev);=0A= if (NULL =3D=3D sc->sysctl_cpu[i]) {=0A= sc->sc_ich.ich_func =3D amdtemp_intrhook;=0A= sc->sc_ich.ich_arg =3D sc;=0A= if (config_intrhook_establish(&sc->sc_ich) !=3D 0) {=0A= amdtemp_detach(dev);=0A= device_printf(dev, "config_intrhook_establish failed!\n");=0A= return (ENXIO);=0A= }=0A= }=0A= return (0);=0A= }=0A= =0A= int=0A= amdtemp_detach(device_t dev) {=0A= struct amdtemp_softc *sc =3D device_get_softc(dev);=0A= uint32_t i;=0A= =0A= for (i =3D 0; i < sc->cpu_ncores; i++)=0A= if (sc->sysctl_cpu[i] !=3D NULL)=0A= sysctl_remove_oid(sc->sysctl_cpu[i], 1, 0);=0A= /* NewBus removes the dev.amdtemp.N tree by itself. */=0A= if (sc->sc_ich.ich_arg !=3D NULL) {=0A= sc->sc_ich.ich_arg =3D NULL;=0A= config_intrhook_disestablish(&sc->sc_ich);=0A= }=0A= mtx_destroy(&sc->lock);=0A= =0A= return (0);=0A= }=0A= =0A= void=0A= amdtemp_intrhook(void *arg) {=0A= struct amdtemp_softc *sc =3D arg;=0A= struct sysctl_ctx_list *sysctlctx;=0A= device_t dev =3D sc->dev, acpi, cpu, nexus;=0A= int (*sysctl_handler)(SYSCTL_HANDLER_ARGS);=0A= intptr_t sysctl_arg2;=0A= uint32_t i, unit_base;=0A= =0A= if (sc->sc_ich.ich_arg !=3D NULL) {=0A= sc->sc_ich.ich_arg =3D NULL;=0A= config_intrhook_disestablish(&sc->sc_ich);=0A= }=0A= =0A= /* dev.cpu.N.temperature. */=0A= nexus =3D device_find_child(root_bus, "nexus", 0);=0A= acpi =3D device_find_child(nexus, "acpi", 0);=0A= unit_base =3D (device_get_unit(dev) * sc->cpu_ncores); /* XXX: = cpu_ncores not constant for different CPUs... */=0A= =0A= for (i =3D 0; i < sc->cpu_ncores; i ++) {=0A= if (sc->sysctl_cpu[i] !=3D NULL)=0A= continue;=0A= cpu =3D device_find_child(acpi, "cpu", (unit_base + i));=0A= if (cpu =3D=3D NULL)=0A= continue;=0A= sysctl_handler =3D NULL;=0A= if (0 !=3D (sc->flags & AMDTEMP_F_TSI)) { /* Temperature Sensor = Interface */=0A= if (0 =3D=3D amdtemp_sbi_read(sc, i, SB_TSI_REG_REVISION))=0A= continue;=0A= sysctl_handler =3D amdtemp_tsi_temp_reg_sysctl;=0A= sysctl_arg2 =3D MAKE_ARG2(SB_TSI_REG_CPU_TEMP_LB,=0A= SB_TSI_REG_CPU_TEMP_HB, i);=0A= } else if (0 !=3D (sc->flags & AMDTEMP_F_RTC)) { /* Reported = Temperature Control */=0A= sysctl_handler =3D amdtemp_rtc_temp_sysctl;=0A= sysctl_arg2 =3D MAKE_ARG2(AMD_REG_REPTMP_CTRL, 21, 11);=0A= } else if (0 !=3D (sc->flags & AMDTEMP_F_TTS)) { /* Thermaltrip Status = */=0A= sysctl_handler =3D amdtemp_tts_temp_reg_sysctl;=0A= sysctl_arg2 =3D MAKE_ARG2(AMD_REG_THERMTRIP_STAT, i, 0xff);=0A= }=0A= if (NULL =3D=3D sysctl_handler)=0A= continue;=0A= sysctlctx =3D device_get_sysctl_ctx(cpu);=0A= sc->sysctl_cpu[i] =3D SYSCTL_ADD_PROC(sysctlctx,=0A= SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO,=0A= "temperature", (CTLTYPE_INT | CTLFLAG_RD), sc, sysctl_arg2,=0A= sysctl_handler, "IK", "Current temparature");=0A= }=0A= }=0A= =0A= =0A= /* Sysctl staff. */=0A= static void=0A= amdtemp_sysctl_reg_add(struct amdtemp_softc *sc, struct sysctl_oid_list = *child,=0A= struct amdtemp_sysctl_reg *regs) {=0A= struct sysctl_ctx_list *ctx =3D device_get_sysctl_ctx(sc->dev);=0A= uint32_t i;=0A= =0A= for (i =3D 0; NULL !=3D regs[i].oid_handler; i ++) {=0A= SYSCTL_ADD_PROC(ctx, child, OID_AUTO, regs[i].name,=0A= regs[i].flags, sc,=0A= MAKE_ARG2(regs[i].reg, regs[i].a1, regs[i].a2),=0A= regs[i].oid_handler, regs[i].fmt, regs[i].descr);=0A= }=0A= }=0A= =0A= static void=0A= amdtemp_sysctl_reg_add2(struct amdtemp_softc *sc, struct sysctl_oid_list = *child,=0A= struct amdtemp_sysctl_reg *regs, uint32_t a2) {=0A= struct sysctl_ctx_list *ctx =3D device_get_sysctl_ctx(sc->dev);=0A= uint32_t i;=0A= =0A= for (i =3D 0; NULL !=3D regs[i].oid_handler; i ++) {=0A= SYSCTL_ADD_PROC(ctx, child, OID_AUTO, regs[i].name,=0A= regs[i].flags, sc,=0A= MAKE_ARG2(regs[i].reg, regs[i].a1, a2),=0A= regs[i].oid_handler, regs[i].fmt, regs[i].descr);=0A= }=0A= }=0A= =0A= static int=0A= amdtemp_sysctl_reg_bits(SYSCTL_HANDLER_ARGS) {=0A= struct amdtemp_softc *sc =3D arg1;=0A= uint32_t i, reg_data, reg_num, bits_off, bits_len, bits_mask =3D 0;=0A= unsigned val;=0A= int error;=0A= =0A= reg_num =3D ARG2_GET_REG(arg2);=0A= bits_off =3D ARG2_GET_A1(arg2);=0A= bits_len =3D ARG2_GET_A2(arg2);=0A= reg_data =3D pci_read_config(sc->dev, reg_num, 4);=0A= =0A= for(i =3D 0; i < bits_len; i ++)=0A= bits_mask |=3D ((uint32_t)1 << i);=0A= =0A= val =3D ((reg_data >> bits_off) & bits_mask);=0A= error =3D sysctl_handle_int(oidp, &val, 0, req);=0A= if (0 !=3D error || NULL =3D=3D req->newptr || val =3D=3D reg_data)=0A= return (error);=0A= reg_data &=3D ~(bits_mask << bits_off); // clear all bits at offset=0A= reg_data |=3D ((val & bits_mask) << bits_off); // set value bits=0A= pci_write_config(sc->dev, reg_num, reg_data, 4);=0A= =0A= return (0);=0A= }=0A= =0A= =0A= /* Thermaltrip Status Register */=0A= static uint32_t=0A= amdtemp_tts_get_temp(struct amdtemp_softc *sc, uint32_t reg, uint8_t = core,=0A= uint8_t sense) {=0A= union reg_amd_thermtrip_status_desc reg_tts;=0A= uint32_t val;=0A= =0A= reg_tts.u32 =3D 0;=0A= if (0 =3D=3D (sc->tts_flags & AMDTEMP_TTS_F_CS_SWAP))=0A= reg_tts.bits.ThermSenseCoreSel =3D ((0 !=3D core) ? 1 : 0);=0A= else /* Swap. */=0A= reg_tts.bits.ThermSenseCoreSel =3D ((0 !=3D core) ? 0 : 1);=0A= reg_tts.bits.ThermSenseSel =3D ((0 !=3D sense) ? 1 : 0);=0A= =0A= AMDTEMP_LOCK(sc);=0A= pci_write_config(sc->dev, reg, reg_tts.u32, 4);=0A= reg_tts.u32 =3D pci_read_config(sc->dev, reg, 4);=0A= AMDTEMP_UNLOCK(sc);=0A= =0A= val =3D reg_tts.bits.CurTmp;=0A= if (0 =3D=3D (sc->tts_flags & AMDTEMP_TTS_F_CT_10BIT))=0A= val &=3D ~3; /* Clear first 2 bits. */=0A= val =3D (AMDTEMP_ZERO_C_TO_K + ((val * 5) / 2) -=0A= ((0 !=3D (sc->tts_flags & AMDTEMP_TTS_F_OFF28)) ? 280 : 490));=0A= val +=3D (sc->tts_temp_offset[((reg_tts.bits.ThermSenseCoreSel << 1) |=0A= reg_tts.bits.ThermSenseSel)] * 10);=0A= =0A= return (val);=0A= }=0A= /* If 0xff =3D=3D ARG2_GET_A2(arg2) then retun max temp for core. */=0A= static int=0A= amdtemp_tts_temp_reg_sysctl(SYSCTL_HANDLER_ARGS) {=0A= struct amdtemp_softc *sc =3D arg1;=0A= uint32_t reg_num;=0A= unsigned val;=0A= int error;=0A= =0A= reg_num =3D ARG2_GET_REG(arg2);=0A= if (0xff =3D=3D ARG2_GET_A2(arg2)) {=0A= val =3D imax(amdtemp_tts_get_temp(sc, reg_num, ARG2_GET_A1(arg2), 0),=0A= amdtemp_tts_get_temp(sc, reg_num, ARG2_GET_A1(arg2), 1));=0A= } else {=0A= val =3D amdtemp_tts_get_temp(sc, reg_num, ARG2_GET_A1(arg2),=0A= ARG2_GET_A2(arg2));=0A= }=0A= error =3D sysctl_handle_int(oidp, &val, 0, req);=0A= if (0 !=3D error || NULL =3D=3D req->newptr)=0A= return (error);=0A= return (0);=0A= }=0A= =0A= =0A= /* D18F3xA4 Reported Temperature Control Register */=0A= static int=0A= amdtemp_rtc_temp_sysctl(SYSCTL_HANDLER_ARGS) {=0A= struct amdtemp_softc *sc =3D arg1;=0A= union reg_amd_rep_tmp_ctrl_desc reg_ctrl;=0A= uint32_t reg_num, bits_off;=0A= unsigned val;=0A= int error;=0A= =0A= reg_num =3D ARG2_GET_REG(arg2);=0A= bits_off =3D ARG2_GET_A1(arg2);=0A= =0A= AMDTEMP_LOCK(sc);=0A= reg_ctrl.u32 =3D pci_read_config(sc->dev, reg_num, 4);=0A= switch (bits_off) {=0A= case 16: /* CurTmpTjSel */=0A= reg_ctrl.bits.CurTmpTjSel =3D 3;=0A= break;=0A= case 21: /* CurTmp */=0A= reg_ctrl.bits.CurTmpTjSel =3D 0;=0A= break;=0A= }=0A= pci_write_config(sc->dev, reg_num, reg_ctrl.u32, 4);=0A= reg_ctrl.u32 =3D pci_read_config(sc->dev, reg_num, 4);=0A= if (bits_off =3D=3D 16) { /* CurTmpTjSel: switch back to CurTmp. */=0A= reg_ctrl.bits.CurTmpTjSel =3D 0;=0A= pci_write_config(sc->dev, reg_num, reg_ctrl.u32, 4);=0A= }=0A= AMDTEMP_UNLOCK(sc);=0A= =0A= val =3D (AMDTEMP_ZERO_C_TO_K + ((reg_ctrl.bits.CurTmp * 5) / 4));=0A= if (16 =3D=3D bits_off) /* CurTmpTjSel */=0A= val -=3D 490;=0A= else=0A= val +=3D (sc->rtc_temp_offset * 10);=0A= error =3D sysctl_handle_int(oidp, &val, 0, req);=0A= if (0 !=3D error || NULL =3D=3D req->newptr)=0A= return (error);=0A= //device_printf(sc->dev, "amdtemp_rtc_temp_sysctl: reg_num =3D %i, = bits_off =3D %i, val =3D %i, reg_ctrl.u32 =3D %i\n", reg_num, bits_off, = val, reg_ctrl.u32);=0A= //pci_write_config(sc->dev, reg_num, reg_ctrl.u32, 4);=0A= return (0);=0A= }=0A= =0A= =0A= /* Set SMBus-based sideband interface address: 0-7. */=0A= static void=0A= amdtemp_sbi_set_addr(struct amdtemp_softc *sc, uint32_t sbi_addr) {=0A= union reg_amd_sbi_ctrl_desc reg_ctrl;=0A= =0A= sbi_addr &=3D AMD_REG_SBI_ADDR_MASK;=0A= reg_ctrl.u32 =3D pci_read_config(sc->dev, AMD_REG_SBI_CTRL, 4);=0A= if (reg_ctrl.bits.SbiAddr =3D=3D sbi_addr) /* Is address allready set? = */=0A= return;=0A= reg_ctrl.bits.SbiAddr =3D sbi_addr;=0A= pci_write_config(sc->dev, AMD_REG_SBI_CTRL, reg_ctrl.u32, 4);=0A= }=0A= =0A= static uint32_t=0A= amdtemp_sbi_read(struct amdtemp_softc *sc, uint32_t sbi_addr, uint32_t = reg_addr) {=0A= uint32_t ret;=0A= =0A= AMDTEMP_LOCK(sc);=0A= amdtemp_sbi_set_addr(sc, sbi_addr);=0A= pci_write_config(sc->dev, AMD_REG_SBI_ADDR, reg_addr, 4);=0A= ret =3D pci_read_config(sc->dev, AMD_REG_SBI_DATA, 4);=0A= AMDTEMP_UNLOCK(sc);=0A= =0A= return (ret);=0A= }=0A= =0A= static int=0A= amdtemp_sbi_write(struct amdtemp_softc *sc, uint32_t sbi_addr, uint32_t = reg_addr,=0A= uint8_t data) {=0A= union reg_amd_sbi_ctrl_desc reg_ctrl;=0A= uint32_t data32 =3D data;=0A= =0A= AMDTEMP_LOCK(sc);=0A= amdtemp_sbi_set_addr(sc, sbi_addr);=0A= pci_write_config(sc->dev, AMD_REG_SBI_ADDR, reg_addr, 4);=0A= pci_write_config(sc->dev, AMD_REG_SBI_DATA, data32, 4);=0A= /* Wait write. */=0A= data32 =3D AMD_SBI_WRITE_TIMEOUT;=0A= while (data32 --) {=0A= reg_ctrl.u32 =3D pci_read_config(sc->dev, AMD_REG_SBI_CTRL, 4);=0A= if (0 !=3D reg_ctrl.bits.SbiRegWrDn)=0A= break;=0A= DELAY(100);=0A= }=0A= AMDTEMP_UNLOCK(sc);=0A= =0A= if (data32 =3D=3D 0) {=0A= device_printf(sc->dev, "timeout waiting for SBI write.\n");=0A= return (1);=0A= }=0A= return (0);=0A= }=0A= =0A= static int=0A= amdtemp_tsi_reg_sysctl(SYSCTL_HANDLER_ARGS) {=0A= struct amdtemp_softc *sc =3D arg1;=0A= uint32_t reg_data, reg_addr, sbi_addr;=0A= unsigned val;=0A= int error;=0A= =0A= reg_addr =3D ARG2_GET_REG(arg2);=0A= sbi_addr =3D (ARG2_GET_A2(arg2) & AMD_REG_SBI_ADDR_MASK);=0A= reg_data =3D amdtemp_sbi_read(sc, sbi_addr, reg_addr);=0A= val =3D reg_data;=0A= =0A= error =3D sysctl_handle_int(oidp, &val, 0, req);=0A= if (0 !=3D error || NULL =3D=3D req->newptr || val =3D=3D reg_data)=0A= return (error);=0A= return (amdtemp_sbi_write(sc, sbi_addr, reg_addr, val));=0A= }=0A= =0A= static int=0A= amdtemp_tsi_temp_reg_sysctl(SYSCTL_HANDLER_ARGS) {=0A= struct amdtemp_softc *sc =3D arg1;=0A= uint32_t reg_data_lo, reg_data_hi, sbi_addr;=0A= unsigned val;=0A= int error;=0A= =0A= sbi_addr =3D (ARG2_GET_A2(arg2) & AMD_REG_SBI_ADDR_MASK);=0A= reg_data_lo =3D amdtemp_sbi_read(sc, sbi_addr, ARG2_GET_REG(arg2));=0A= reg_data_hi =3D amdtemp_sbi_read(sc, sbi_addr, ARG2_GET_A1(arg2));=0A= val =3D (AMDTEMP_ZERO_C_TO_K + (reg_data_hi * 10));=0A= if (SB_TSI_REG_CPU_TEMP_LB =3D=3D ARG2_GET_REG(arg2)) /* Apply offset = only to sensor. */=0A= val +=3D (sc->tsi_temp_offset[sbi_addr] * 10);=0A= if (reg_data_lo & 0x80)=0A= val +=3D 5; /* 0,5 C */=0A= if (reg_data_lo & 0x40)=0A= val +=3D 3; /* 0,25 C */=0A= if (reg_data_lo & 0x20)=0A= val +=3D 1; /* 0,125 C */=0A= =0A= error =3D sysctl_handle_int(oidp, &val, 0, req);=0A= if (0 !=3D error || NULL =3D=3D req->newptr)=0A= return (error);=0A= return (0);=0A= }=0A= ------=_NextPart_000_0206_01CEC31D.875A19E0--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?52520d5f.c402cd0a.5f4e.ffffffa2>