Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-6]: src/sys/dev/i2c Pull up following revision(s) (requested by m...



details:   https://anonhg.NetBSD.org/src/rev/0e64deac9822
branches:  netbsd-6
changeset: 776417:0e64deac9822
user:      riz <riz%NetBSD.org@localhost>
date:      Sat Aug 10 22:50:56 2013 +0000

description:
Pull up following revision(s) (requested by matt in ticket #929):
        sys/dev/i2c/w83795g.c: revision 1.1
        sys/dev/i2c/w83795greg.h: revision 1.1
        sys/dev/i2c/files.i2c: revision 1.50
Add driver for Nuvoton W83795G voltage/temp/fan/gpio monitoring device.
As used in the HP Microserver N36L/N40L/N54L:
w83795g* at iic? addr 0x2f
gpio* at gpiobus?
Note that the gpio and watchdog functionality appears to be useless on
the Microserver, as the gpio pins don't affect the LED's and a watchdog
trigger does not cause a reset. Perhaps the reset pin just isn't wired.
There are quite flexible fan control options as well as just monitoring,
but it is not clear to me how best to export that function to userspace.

diffstat:

 sys/dev/i2c/files.i2c    |    7 +-
 sys/dev/i2c/w83795g.c    |  452 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/i2c/w83795greg.h |  434 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 892 insertions(+), 1 deletions(-)

diffs (truncated from 912 to 300 lines):

diff -r 91224976f20f -r 0e64deac9822 sys/dev/i2c/files.i2c
--- a/sys/dev/i2c/files.i2c     Sat Aug 10 22:42:29 2013 +0000
+++ b/sys/dev/i2c/files.i2c     Sat Aug 10 22:50:56 2013 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.i2c,v 1.45 2011/11/18 22:18:08 jmcneill Exp $
+#      $NetBSD: files.i2c,v 1.45.6.1 2013/08/10 22:50:56 riz Exp $
 
 obsolete defflag       opt_i2cbus.h            I2C_SCAN
 define i2cbus { }
@@ -171,3 +171,8 @@
 device ibmhawk: sysmon_envsys
 attach ibmhawk at iic
 file   dev/i2c/ibmhawk.c               ibmhawk
+ 
+# Nuvoton W83795G/ADG Hardware Monitor
+device w83795g: gpiobus, sysmon_envsys, sysmon_wdog
+attach w83795g at iic
+file   dev/i2c/w83795g.c               w83795g
diff -r 91224976f20f -r 0e64deac9822 sys/dev/i2c/w83795g.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/i2c/w83795g.c     Sat Aug 10 22:50:56 2013 +0000
@@ -0,0 +1,452 @@
+/*     $NetBSD: w83795g.c,v 1.1.2.2 2013/08/10 22:50:56 riz Exp $      */
+
+/*
+ * Copyright (c) 2013 Soren S. Jorvang.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: w83795g.c,v 1.1.2.2 2013/08/10 22:50:56 riz Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/gpio.h>
+#include <sys/wdog.h>
+
+#include <dev/i2c/i2cvar.h>
+#include <dev/gpio/gpiovar.h>    
+#include <dev/sysmon/sysmonvar.h>
+
+#include <dev/i2c/w83795greg.h>
+
+#define NUM_SENSORS 53
+static const struct w83795g_sensor {
+       const char *desc;
+       enum envsys_units type;
+       uint8_t en_reg;
+       uint8_t en_mask;
+       uint8_t en_bits;
+       uint8_t msb;
+} sensors[NUM_SENSORS] = {
+#define _VOLT ENVSYS_SVOLTS_DC
+       { "VSEN1",   _VOLT, W83795G_V_CTRL1, 0x01, 0x01, W83795G_VSEN1 },
+       { "VSEN2",   _VOLT, W83795G_V_CTRL1, 0x02, 0x02, W83795G_VSEN2 },
+       { "VSEN3",   _VOLT, W83795G_V_CTRL1, 0x04, 0x04, W83795G_VSEN3 },
+       { "VSEN4",   _VOLT, W83795G_V_CTRL1, 0x08, 0x08, W83795G_VSEN4 },
+       { "VSEN5",   _VOLT, W83795G_V_CTRL1, 0x10, 0x10, W83795G_VSEN5 },
+       { "VSEN6",   _VOLT, W83795G_V_CTRL1, 0x20, 0x20, W83795G_VSEN6 },
+       { "VSEN7",   _VOLT, W83795G_V_CTRL1, 0x40, 0x40, W83795G_VSEN7 },
+       { "VSEN8",   _VOLT, W83795G_V_CTRL1, 0x80, 0x80, W83795G_VSEN8 },
+       { "VSEN9",   _VOLT, W83795G_V_CTRL2, 0x01, 0x01, W83795G_VSEN9 },
+       { "VSEN10",  _VOLT, W83795G_V_CTRL2, 0x02, 0x02, W83795G_VSEN10 },
+       { "VSEN11",  _VOLT, W83795G_V_CTRL2, 0x04, 0x04, W83795G_VSEN11 },
+       { "VTT",     _VOLT, W83795G_V_CTRL2, 0x08, 0x08, W83795G_VTT },
+       { "3VDD",    _VOLT, W83795G_V_CTRL2, 0x10, 0x10, W83795G_3VDD },
+       { "3VSB",    _VOLT, W83795G_V_CTRL2, 0x20, 0x20, W83795G_3VSB },
+       { "VBAT",    _VOLT, W83795G_V_CTRL2, 0x40, 0x40, W83795G_VBAT },
+       { "VSEN12",  _VOLT, W83795G_T_CTRL1, 0x03, 0x02, W83795G_VSEN12 },
+       { "VSEN13",  _VOLT, W83795G_T_CTRL1, 0x0c, 0x08, W83795G_VSEN13 },
+       { "VDSEN14", _VOLT, W83795G_T_CTRL2, 0x03, 0x02, W83795G_VDSEN14 },
+       { "VDSEN15", _VOLT, W83795G_T_CTRL2, 0x0c, 0x08, W83795G_VDSEN15 },
+       { "VDSEN16", _VOLT, W83795G_T_CTRL2, 0x30, 0x20, W83795G_VDSEN16 },
+       { "VDSEN17", _VOLT, W83795G_T_CTRL2, 0xc0, 0x80, W83795G_VDSEN17 },
+#define _TEMP ENVSYS_STEMP
+       { "TR5",     _TEMP, W83795G_T_CTRL1, 0x03, 0x03, W83795G_TR5 },
+       { "TR6",     _TEMP, W83795G_T_CTRL1, 0x0c, 0x0c, W83795G_TR6 },
+       { "TD1",     _TEMP, W83795G_T_CTRL2, 0x03, 0x01, W83795G_TD1 },
+       { "TD2",     _TEMP, W83795G_T_CTRL2, 0x0c, 0x04, W83795G_TD2 },
+       { "TD3",     _TEMP, W83795G_T_CTRL2, 0x30, 0x10, W83795G_TD3 },
+       { "TD4",     _TEMP, W83795G_T_CTRL2, 0xc0, 0x40, W83795G_TD4 },
+       { "TR1",     _TEMP, W83795G_T_CTRL2, 0x03, 0x03, W83795G_TR1 },
+       { "TR2",     _TEMP, W83795G_T_CTRL2, 0x0c, 0x0c, W83795G_TR2 },
+       { "TR3",     _TEMP, W83795G_T_CTRL2, 0x30, 0x30, W83795G_TR3 },
+       { "TR4",     _TEMP, W83795G_T_CTRL2, 0xc0, 0xc0, W83795G_TR4 },
+       { "DTS1",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS1 },
+       { "DTS2",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS2 },
+       { "DTS3",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS3 },
+       { "DTS4",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS4 },
+       { "DTS5",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS5 },
+       { "DTS6",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS6 },
+       { "DTS7",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS7 },
+       { "DTS8",    _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS8 },
+#define _FAN ENVSYS_SFANRPM
+       { "FANIN1",  _FAN,  W83795G_F_CTRL1, 0x01, 0x01, W83795G_FANIN1 },
+       { "FANIN2",  _FAN,  W83795G_F_CTRL1, 0x02, 0x02, W83795G_FANIN2 },
+       { "FANIN3",  _FAN,  W83795G_F_CTRL1, 0x04, 0x04, W83795G_FANIN3 },
+       { "FANIN4",  _FAN,  W83795G_F_CTRL1, 0x08, 0x08, W83795G_FANIN4 },
+       { "FANIN5",  _FAN,  W83795G_F_CTRL1, 0x10, 0x10, W83795G_FANIN5 },
+       { "FANIN6",  _FAN,  W83795G_F_CTRL1, 0x20, 0x20, W83795G_FANIN6 },
+       { "FANIN7",  _FAN,  W83795G_F_CTRL1, 0x40, 0x40, W83795G_FANIN7 },
+       { "FANIN8",  _FAN,  W83795G_F_CTRL1, 0x80, 0x80, W83795G_FANIN8 },
+       { "FANIN9",  _FAN,  W83795G_F_CTRL2, 0x01, 0x01, W83795G_FANIN9 },
+       { "FANIN10", _FAN,  W83795G_F_CTRL2, 0x02, 0x02, W83795G_FANIN10 },
+       { "FANIN11", _FAN,  W83795G_F_CTRL2, 0x04, 0x04, W83795G_FANIN11 },
+       { "FANIN12", _FAN,  W83795G_F_CTRL2, 0x08, 0x08, W83795G_FANIN12 },
+       { "FANIN13", _FAN,  W83795G_F_CTRL2, 0x10, 0x10, W83795G_FANIN13 },
+       { "FANIN14", _FAN,  W83795G_F_CTRL2, 0x20, 0x20, W83795G_FANIN14 },
+};
+
+struct w83795g_softc {
+       device_t                sc_dev;
+       i2c_tag_t               sc_tag;
+       i2c_addr_t              sc_addr;
+       struct gpio_chipset_tag sc_gpio_gc;
+       gpio_pin_t              sc_gpio_pins[8];
+       struct sysmon_envsys    *sc_sme;
+       envsys_data_t           sc_sensors[NUM_SENSORS];
+       struct sysmon_wdog      sc_smw;
+};
+
+static int     w83795g_match(device_t, cfdata_t, void *);
+static void    w83795g_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(w83795g, sizeof(struct w83795g_softc),
+    w83795g_match, w83795g_attach, NULL, NULL);
+
+static void    w83795g_refresh(struct sysmon_envsys *, envsys_data_t *);
+static void    w83795g_get_limits(struct sysmon_envsys *, envsys_data_t *,
+   sysmon_envsys_lim_t *limits, uint32_t *props);
+
+static int     w83795g_gpio_read(void *, int);   
+static void    w83795g_gpio_write(void *, int, int); 
+static void    w83795g_gpio_ctl(void *, int, int);
+
+static int     w83795g_wdog_setmode(struct sysmon_wdog *);
+static int     w83795g_wdog_tickle(struct sysmon_wdog *);
+
+static int
+w83795g_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct i2c_attach_args *ia = aux;
+       uint8_t bank, vend, chip, deva;
+
+       if (ia->ia_addr < I2CADDR_MINADDR || ia->ia_addr > I2CADDR_MAXADDR)
+               return 0;
+
+       iic_acquire_bus(ia->ia_tag, 0);
+       iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_BANKSEL, &bank, 0);
+       iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_VENDOR, &vend, 0);
+       iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_CHIP, &chip, 0);
+       iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_DEVICEA, &deva, 0);
+       iic_release_bus(ia->ia_tag, 0);
+
+       if ((bank & BANKSEL_HBACS && vend == VENDOR_NUVOTON_ID_HI) ||
+          (~bank & BANKSEL_HBACS && vend == VENDOR_NUVOTON_ID_LO))
+               if (chip == CHIP_W83795G && deva == DEVICEA_A)
+                       return 1;
+
+       return 0;
+}
+
+static void
+w83795g_attach(device_t parent, device_t self, void *aux)
+{
+       struct w83795g_softc *sc = device_private(self);
+       struct i2c_attach_args *ia = aux;
+       struct gpiobus_attach_args gba;
+       uint8_t conf, rev, reg, gpiom, en_reg;
+       int i;
+
+       sc->sc_dev = self;
+       sc->sc_tag = ia->ia_tag;
+       sc->sc_addr = ia->ia_addr;
+       sc->sc_gpio_gc.gp_cookie = sc;
+       sc->sc_gpio_gc.gp_pin_read = w83795g_gpio_read;
+       sc->sc_gpio_gc.gp_pin_write = w83795g_gpio_write;
+       sc->sc_gpio_gc.gp_pin_ctl = w83795g_gpio_ctl;
+       sc->sc_sme = sysmon_envsys_create();
+       sc->sc_sme->sme_name = device_xname(self);
+       sc->sc_sme->sme_cookie = sc;
+       sc->sc_sme->sme_refresh = w83795g_refresh;
+       sc->sc_sme->sme_get_limits = w83795g_get_limits;
+       sc->sc_smw.smw_name = device_xname(self);
+       sc->sc_smw.smw_cookie = sc;
+       sc->sc_smw.smw_setmode = w83795g_wdog_setmode;
+       sc->sc_smw.smw_tickle = w83795g_wdog_tickle;
+       sc->sc_smw.smw_period = 60;
+
+       iic_acquire_bus(sc->sc_tag, 0);
+       iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
+       iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_CONFIG, &conf, 0);
+       iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_DEVICE, &rev, 0);
+
+       aprint_normal(": Nuvaton W83795");
+       if (conf & CONFIG_CONFIG48)
+               aprint_normal("ADG");
+       else
+               aprint_normal("G");
+       aprint_verbose(" (rev %c)", rev - DEVICEA_A + 'A');
+       aprint_normal(" Hardware Monitor\n");
+       aprint_naive(": Hardware Monitor\n");
+
+       /* Debug dump of all register banks */
+       for (i = 0; i < 1024; i++) {
+               if (i % 256 == 0) {
+                       iic_smbus_write_byte(sc->sc_tag, sc->sc_addr,
+                           W83795G_BANKSEL, i / 256, 0);
+                       aprint_debug_dev(self, "register bank %d:\n", i / 256);
+               }
+               if (i % 32 == 0)
+                       aprint_debug_dev(self, "%02x ", i % 256);
+               iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, i % 256, &reg, 0);
+               aprint_debug("%02x", reg);
+               if (i % 32 == 31)
+                       aprint_debug("\n");
+               else if (i % 8 == 7)
+                       aprint_debug(" ");
+       }
+
+       iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
+
+       for (i = 0; i < NUM_SENSORS; i++) {
+               iic_smbus_read_byte(sc->sc_tag, sc->sc_addr,
+                   sensors[i].en_reg, &en_reg, 0);
+
+               if ((en_reg & sensors[i].en_mask) != sensors[i].en_bits)
+                       continue;
+               
+               strcpy(sc->sc_sensors[i].desc, sensors[i].desc);
+               sc->sc_sensors[i].units = sensors[i].type;
+               sc->sc_sensors[i].state = ENVSYS_SINVALID;
+               sc->sc_sensors[i].flags = ENVSYS_FMONLIMITS;
+               sc->sc_sensors[i].flags |= ENVSYS_FHAS_ENTROPY;
+               sc->sc_sensors[i].private = i;
+               sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensors[i]);
+       }
+
+       iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_M, &gpiom, 0);
+       iic_release_bus(sc->sc_tag, 0);
+       
+       if (conf & CONFIG_CONFIG48)
+               gba.gba_npins = 4;
+       else
+               gba.gba_npins = 8;
+       gba.gba_gc = &sc->sc_gpio_gc;
+       gba.gba_pins = sc->sc_gpio_pins;
+
+       for (i = 0; i < gba.gba_npins; i++) {
+               sc->sc_gpio_pins[i].pin_num = i;  
+               sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_OUTPUT | GPIO_PIN_INPUT;
+               sc->sc_gpio_pins[i].pin_flags = (gpiom & (1 << i)) ?
+                   GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+               sc->sc_gpio_pins[i].pin_state = w83795g_gpio_read(sc, i);
+       }
+
+       if (sysmon_envsys_register(sc->sc_sme))
+               aprint_error_dev(self, "unable to register with sysmon\n");
+
+       if (sysmon_wdog_register(&sc->sc_smw) != 0)
+               aprint_error_dev(self, "couldn't register watchdog\n");
+
+       if (!pmf_device_register(self, NULL, NULL))
+               aprint_error_dev(self, "couldn't establish power handler\n");
+
+       config_found(self, &gba, gpiobus_print);
+}
+
+static void
+w83795g_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
+{
+       struct w83795g_softc *sc = sme->sme_cookie;
+       const struct w83795g_sensor *sensor = &sensors[edata->private];
+       uint8_t msb, lsb;
+
+       sensor = &sensors[edata->private];
+
+       iic_acquire_bus(sc->sc_tag, 0);



Home | Main Index | Thread Index | Old Index