From 2ce4c48f84acfe400f902568ebf61d96d69e42b8 Mon Sep 17 00:00:00 2001 From: Imre Vadasz Date: Mon, 20 Oct 2014 21:23:19 +0200 Subject: [PATCH] wbsio: support NCT6776F (0xc3); supported by lm(4) as W83627DHG (0xc1) The sc_devid value of struct wbsio_softc is used to pass the device id of the SUPERIO chipset to lm, so it can decide whether it's actually an NCT6776F or the W83627DHG. Taken-From: OpenBSD --- sys/config/X86_64_GENERIC | 3 +- sys/dev/powermng/lm/lm78.c | 56 ++++++++++++++++++++- sys/dev/powermng/lm/lm78_isa.c | 28 +++++++++-- sys/dev/powermng/lm/lm78var.h | 4 +- sys/dev/powermng/wbsio/wbsio.c | 101 ++++++++------------------------------ sys/dev/powermng/wbsio/wbsioreg.h | 54 ++++++++++++++++++++ sys/dev/powermng/wbsio/wbsiovar.h | 27 ++++++++++ 7 files changed, 185 insertions(+), 88 deletions(-) create mode 100644 sys/dev/powermng/wbsio/wbsioreg.h create mode 100644 sys/dev/powermng/wbsio/wbsiovar.h diff --git a/sys/config/X86_64_GENERIC b/sys/config/X86_64_GENERIC index 349e43b..bf4c4c9 100644 --- a/sys/config/X86_64_GENERIC +++ b/sys/config/X86_64_GENERIC @@ -182,7 +182,8 @@ device it2 at isa? port 0xd00 device it3 at isa? port 0x228 device wbsio0 at isa? port 0x2e device wbsio1 at isa? port 0x4e -device lm#3 at wbsio? +device lm1 at wbsio0 +device lm2 at wbsio1 # Intel Core and newer CPUs on-die digital thermal sensor support device coretemp device dimm # DIMM information (location, etc.) diff --git a/sys/dev/powermng/lm/lm78.c b/sys/dev/powermng/lm/lm78.c index 6cac2a3..9f1c076 100644 --- a/sys/dev/powermng/lm/lm78.c +++ b/sys/dev/powermng/lm/lm78.c @@ -23,6 +23,7 @@ #include #include "lm78var.h" +#include "../wbsio/wbsioreg.h" #if defined(LMDEBUG) #define DPRINTF(x) do { kprintf x; } while (0) @@ -59,6 +60,7 @@ void wb_refresh_nvolt(struct lm_softc *, int); void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int); void wb_refresh_temp(struct lm_softc *, int); void wb_refresh_fanrpm(struct lm_softc *, int); +void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int); void wb_w83792d_refresh_fanrpm(struct lm_softc *, int); void as_refresh_temp(struct lm_softc *, int); @@ -181,6 +183,33 @@ struct lm_sensor w83627dhg_sensors[] = { { NULL } }; +struct lm_sensor nct6776f_sensors[] = { + /* Voltage */ + { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2}, + { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 }, + { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 }, + { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 }, + { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt }, + { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 }, + { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 }, + { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 }, + { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 }, + + /* Temperature */ + { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, + { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, + { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, + + /* Fans */ + { "", SENSOR_FANRPM, 6, 0x56, wb_nct6776f_refresh_fanrpm }, + { "", SENSOR_FANRPM, 6, 0x58, wb_nct6776f_refresh_fanrpm }, + { "", SENSOR_FANRPM, 6, 0x5a, wb_nct6776f_refresh_fanrpm }, + { "", SENSOR_FANRPM, 6, 0x5c, wb_nct6776f_refresh_fanrpm }, + { "", SENSOR_FANRPM, 6, 0x5e, wb_nct6776f_refresh_fanrpm }, + + { NULL } +}; + struct lm_sensor w83637hf_sensors[] = { /* Voltage */ { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore }, @@ -521,8 +550,13 @@ wb_match(struct lm_softc *sc) lm_setup_sensors(sc, w83627ehf_sensors); break; case WB_CHIPID_W83627DHG: - cdesc = "W83627DHG"; - lm_setup_sensors(sc, w83627dhg_sensors); + if (sc->sioid == WBSIO_ID_NCT6776F) { + cdesc = "NCT6776F"; + lm_setup_sensors(sc, nct6776f_sensors); + } else { + cdesc = "W83627DHG"; + lm_setup_sensors(sc, w83627dhg_sensors); + } break; case WB_CHIPID_W83637HF: cdesc = "W83637HF"; @@ -882,6 +916,24 @@ wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n) } void +wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n) +{ + struct ksensor *sensor = &sc->sensors[n]; + int datah, datal; + + datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg); + datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1); + + if (datah == 0xff) { + sensor->flags |= SENSOR_FINVALID; + sensor->value = 0; + } else { + sensor->flags &= ~SENSOR_FINVALID; + sensor->value = (datah << 8) | datal; + } +} + +void as_refresh_temp(struct lm_softc *sc, int n) { struct ksensor *sensor = &sc->sensors[n]; diff --git a/sys/dev/powermng/lm/lm78_isa.c b/sys/dev/powermng/lm/lm78_isa.c index ccff547..7a7936f 100644 --- a/sys/dev/powermng/lm/lm78_isa.c +++ b/sys/dev/powermng/lm/lm78_isa.c @@ -30,6 +30,8 @@ #include #include "lm78var.h" +#include "../wbsio/wbsioreg.h" +#include "../wbsio/wbsiovar.h" /* ISA registers */ #define LMC_ADDR 0x05 @@ -75,17 +77,30 @@ static driver_t lm_isa_driver = { static devclass_t lm_devclass; DRIVER_MODULE(lm, isa, lm_isa_driver, lm_devclass, NULL, NULL); +DRIVER_MODULE(lm, wbsio, lm_isa_driver, lm_devclass, NULL, NULL); int lm_isa_probe(struct device *dev) { struct lm_isa_softc *sc = device_get_softc(dev); + struct wbsio_softc *wbsc = NULL; struct resource *iores; + struct devclass *parent_devclass; + const char *parent_name; int iorid = 0; bus_space_tag_t iot; bus_space_handle_t ioh; int banksel, vendid, chipid, addr; + parent_devclass = device_get_devclass(device_get_parent(dev)); + parent_name = devclass_get_name(parent_devclass); + if (strcmp("wbsio", parent_name) == 0) { + wbsc = device_get_softc(device_get_parent(dev)); + sc->sc_lmsc.sioid = wbsc->sc_devid; + } else { + sc->sc_lmsc.sioid = 0; + } + iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid, 0ul, ~0ul, 8, RF_ACTIVE); if (iores == NULL) { @@ -98,10 +113,17 @@ lm_isa_probe(struct device *dev) /* Probe for Winbond chips. */ bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL); banksel = bus_space_read_1(iot, ioh, LMC_DATA); + bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL); + bus_space_write_1(iot, ioh, LMC_DATA, WB_BANKSEL_HBAC); bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID); - vendid = bus_space_read_1(iot, ioh, LMC_DATA); - if (((banksel & 0x80) && vendid == (WB_VENDID_WINBOND >> 8)) || - (!(banksel & 0x80) && vendid == (WB_VENDID_WINBOND & 0xff))) + vendid = bus_space_read_1(iot, ioh, LMC_DATA) << 8; + bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL); + bus_space_write_1(iot, ioh, LMC_DATA, 0); + bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID); + vendid |= bus_space_read_1(iot, ioh, LMC_DATA); + bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL); + bus_space_write_1(iot, ioh, LMC_DATA, banksel); + if (vendid == WB_VENDID_WINBOND) goto found; /* Probe for ITE chips (and don't attach if we find one). */ diff --git a/sys/dev/powermng/lm/lm78var.h b/sys/dev/powermng/lm/lm78var.h index ac98e41..426042f 100644 --- a/sys/dev/powermng/lm/lm78var.h +++ b/sys/dev/powermng/lm/lm78var.h @@ -114,7 +114,7 @@ #define WB_CHIPID_W83627EHF_A 0x88 /* early version, only for ASUS MBs */ #define WB_CHIPID_W83627THF 0x90 #define WB_CHIPID_W83627EHF 0xa1 -#define WB_CHIPID_W83627DHG 0xc1 +#define WB_CHIPID_W83627DHG 0xc1 /* also used in WBSIO_ID_NCT6776F */ /* Config bits */ #define WB_CONFIG_VMR9 0x01 @@ -150,7 +150,9 @@ struct lm_softc { u_int8_t sbusaddr; u_int8_t chipid; + u_int8_t sioid; u_int8_t vrm9; + }; void lm_probe(struct lm_softc *); diff --git a/sys/dev/powermng/wbsio/wbsio.c b/sys/dev/powermng/wbsio/wbsio.c index bbc2ffe..b8afcfd 100644 --- a/sys/dev/powermng/wbsio/wbsio.c +++ b/sys/dev/powermng/wbsio/wbsio.c @@ -29,49 +29,10 @@ #include #include +#include -/* ISA bus registers */ -#define WBSIO_INDEX 0x00 /* Configuration Index Register */ -#define WBSIO_DATA 0x01 /* Configuration Data Register */ - -#define WBSIO_IOSIZE 0x02 /* ISA I/O space size */ - -#define WBSIO_CONF_EN_MAGIC 0x87 /* enable configuration mode */ -#define WBSIO_CONF_DS_MAGIC 0xaa /* disable configuration mode */ - -/* Configuration Space Registers */ -#define WBSIO_LDN 0x07 /* Logical Device Number */ -#define WBSIO_ID 0x20 /* Device ID */ -#define WBSIO_REV 0x21 /* Device Revision */ - -#define WBSIO_ID_W83627HF 0x52 -#define WBSIO_ID_W83627THF 0x82 -#define WBSIO_ID_W83627EHF 0x88 -#define WBSIO_ID_W83627DHG 0xa0 -#define WBSIO_ID_W83627DHGP 0xb0 -#define WBSIO_ID_W83627SF 0x59 -#define WBSIO_ID_W83627UHG 0xa2 -#define WBSIO_ID_W83637HF 0x70 -#define WBSIO_ID_W83667HG 0xa5 -#define WBSIO_ID_W83687THF 0x85 -#define WBSIO_ID_W83697HF 0x60 - -/* Logical Device Number (LDN) Assignments */ -#define WBSIO_LDN_HM 0x0b - -/* Hardware Monitor Control Registers (LDN B) */ -#define WBSIO_HM_ADDR_MSB 0x60 /* Address [15:8] */ -#define WBSIO_HM_ADDR_LSB 0x61 /* Address [7:0] */ - -struct wbsio_softc { - struct device *sc_dev; - - struct resource *sc_iores; - int sc_iorid; - - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; -}; +#include "wbsioreg.h" +#include "wbsiovar.h" static void wbsio_identify(driver_t *, struct device *); static int wbsio_probe(struct device *); @@ -79,12 +40,21 @@ static int wbsio_attach(struct device *); static int wbsio_detach(struct device *); static device_method_t wbsio_methods[] = { + /* Device interface */ DEVMETHOD(device_identify, wbsio_identify), DEVMETHOD(device_probe, wbsio_probe), DEVMETHOD(device_attach, wbsio_attach), DEVMETHOD(device_detach, wbsio_detach), - { NULL, NULL} + /* Bus interface */ + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_set_resource, bus_generic_set_resource), + DEVMETHOD(bus_alloc_resource, isa_alloc_resource), + DEVMETHOD(bus_release_resource, isa_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + + DEVMETHOD_END }; static driver_t wbsio_driver = { @@ -213,6 +183,9 @@ wbsio_probe(struct device *dev) case WBSIO_ID_W83697HF: desc = "W83697HF"; break; + case WBSIO_ID_NCT6776F: + desc = "NCT6776F"; + break; } if (desc == NULL) { @@ -239,10 +212,7 @@ wbsio_attach(struct device *dev) struct wbsio_softc *sc = device_get_softc(dev); uint8_t reg0, reg1; uint16_t iobase; - struct device *parent = device_get_parent(dev); struct device *child; - struct devclass *c_dc; - int c_maxunit; /* Map ISA I/O space */ sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid, @@ -258,6 +228,9 @@ wbsio_attach(struct device *dev) /* Enter configuration mode */ wbsio_conf_enable(sc->sc_iot, sc->sc_ioh); + /* Read device ID */ + sc->sc_devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); + /* Select HM logical device */ wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); @@ -280,41 +253,7 @@ wbsio_attach(struct device *dev) return 0; } - child = NULL; - c_dc = devclass_find("lm"); - if (c_dc == NULL) { - device_printf(dev, "lm devclass not found\n"); - return ENXIO; - } - c_maxunit = devclass_get_maxunit(c_dc); - for (int u = 0; u < c_maxunit; u++) { - child = devclass_get_device(c_dc, u); - if (child == NULL) - continue; - if (isa_get_port(child) == iobase) { - if (device_is_attached(child)) { - device_printf(dev, - "%s is already attached at 0x%x\n", - device_get_nameunit(child), iobase); - return 0; - } - break; - } - if (device_is_attached(child)) { - child = NULL; - continue; - } - device_printf(dev, - "found unused %s at 0x%x with state %i, reusing at 0x%x\n", - device_get_nameunit(child), isa_get_port(child), - device_get_state(child), iobase); - break; - } - if (child == NULL) - child = BUS_ADD_CHILD(parent, parent, ISA_ORDER_PNP, - "lm", -1); -// child = BUS_ADD_CHILD(parent, parent, ISA_ORDER_PNP, -// "lm", 3 + device_get_unit(dev)); + child = BUS_ADD_CHILD(dev, dev, 0, "lm", -1); if (child == NULL) { device_printf(dev, "cannot add child\n"); return ENXIO; diff --git a/sys/dev/powermng/wbsio/wbsioreg.h b/sys/dev/powermng/wbsio/wbsioreg.h new file mode 100644 index 0000000..45dbe01 --- /dev/null +++ b/sys/dev/powermng/wbsio/wbsioreg.h @@ -0,0 +1,54 @@ +/* $OpenBSD: wbsioreg.h,v 1.3 2012/07/01 02:15:09 lteo Exp $ */ +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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. + */ + +/* + * Winbond LPC Super I/O driver registers + */ + +/* ISA bus registers */ +#define WBSIO_INDEX 0x00 /* Configuration Index Register */ +#define WBSIO_DATA 0x01 /* Configuration Data Register */ + +#define WBSIO_IOSIZE 0x02 /* ISA I/O space size */ + +#define WBSIO_CONF_EN_MAGIC 0x87 /* enable configuration mode */ +#define WBSIO_CONF_DS_MAGIC 0xaa /* disable configuration mode */ + +/* Configuration Space Registers */ +#define WBSIO_LDN 0x07 /* Logical Device Number */ +#define WBSIO_ID 0x20 /* Device ID */ +#define WBSIO_REV 0x21 /* Device Revision */ + +#define WBSIO_ID_W83627HF 0x52 +#define WBSIO_ID_W83627THF 0x82 +#define WBSIO_ID_W83627EHF 0x88 +#define WBSIO_ID_W83627DHG 0xa0 +#define WBSIO_ID_W83627DHGP 0xb0 +#define WBSIO_ID_W83627UHG 0xa2 +#define WBSIO_ID_W83627SF 0x59 +#define WBSIO_ID_W83637HF 0x70 +#define WBSIO_ID_W83667HG 0xa5 +#define WBSIO_ID_W83687THF 0x85 +#define WBSIO_ID_W83697HF 0x60 +#define WBSIO_ID_NCT6776F 0xc3 + +/* Logical Device Number (LDN) Assignments */ +#define WBSIO_LDN_HM 0x0b + +/* Hardware Monitor Control Registers (LDN B) */ +#define WBSIO_HM_ADDR_MSB 0x60 /* Address [15:8] */ +#define WBSIO_HM_ADDR_LSB 0x61 /* Address [7:0] */ diff --git a/sys/dev/powermng/wbsio/wbsiovar.h b/sys/dev/powermng/wbsio/wbsiovar.h new file mode 100644 index 0000000..104b486 --- /dev/null +++ b/sys/dev/powermng/wbsio/wbsiovar.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 Imre Vadász + * + * 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. + */ + +struct wbsio_softc { + struct device *sc_dev; + + struct resource *sc_iores; + int sc_iorid; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + int sc_devid; +}; -- 2.4.2