Subject: Re: VIA VT82C686A and VT8231 testers wanted
To: Juan RP <juan@xtrarom.org>
From: Nicolas Joly <njoly@pasteur.fr>
List: port-i386
Date: 01/14/2007 23:10:29
--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, Jan 14, 2007 at 12:22:19AM +0100, Juan RP wrote:
> On Sat, 13 Jan 2007 23:43:16 +0100
> Nicolas Joly <njoly@pasteur.fr> wrote:
> 
> > I just tested it on a HP Pavillion 7825, which has a VIA VT86C686A
> > chipset; and i can report that it works (dmesg attached).
> > 
> > In the mean time, i noted a few things:
> > 
> > 1) dmesg output can be improved (by removing some extra newlines).
> > 
> > [...]
> > uhub1: 2 ports with 2 removable, self powered
> > viaenv0 at pci0 dev 7 function 4
> > : VIA VT82C686A Hardware Monitor
> > timecounter: Timecounter "viaenv0" frequency 3579545 Hz quality 1000
> > viaenv0 24-bit timer
> > 
> > auvia0 at pci0 dev 7 function 5: VIA Technologies VT82C686A AC'97
> > Audio (rev H) [...]
> 
> Fixed.

Unfortunately, the empty line remains. Here is a slightly modified
version of your patch i currently use.

I prefer to systematically print the chipset/function description, and
eventually add some extra messages when things goes wrong.

-- 
Nicolas Joly

Biological Software and Databanks.
Institut Pasteur, Paris.

--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="netbsd-viaenv.diff"

Index: sys/dev/pci/files.pci
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/files.pci,v
retrieving revision 1.275
diff -u -r1.275 files.pci
--- sys/dev/pci/files.pci	17 Dec 2006 23:02:06 -0000	1.275
+++ sys/dev/pci/files.pci	14 Jan 2007 21:49:46 -0000
@@ -660,15 +660,10 @@
 attach	btvmeii at pci
 file	dev/pci/btvmeii.c btvmeii
 
-# VT86C686A power management
-device	viapm {}
-attach	viapm at pci
-file	dev/pci/viapm.c	viapm
-
-# hardware monitoring part of viapm
-device	viaenv: sysmon_envsys
-attach	viaenv at viapm
-file	dev/pci/viaenv.c		viaenv			needs-flag
+# VIA VT82C686A/VT8231 PM Timer and Hardware Monitor
+device	viaenv: acpipmtimer, sysmon_envsys
+attach	viaenv at pci
+file	dev/pci/viaenv.c		viaenv
 
 # Intel PIIX4 power management controller
 device	piixpm: i2cbus, acpipmtimer
Index: sys/dev/pci/viaenv.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/viaenv.c,v
retrieving revision 1.17
diff -u -r1.17 viaenv.c
--- sys/dev/pci/viaenv.c	16 Nov 2006 01:33:10 -0000	1.17
+++ sys/dev/pci/viaenv.c	14 Jan 2007 21:49:48 -0000
@@ -32,7 +32,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* driver for the hardware monitoring part of the VIA VT82C686A */
+/*
+ * Driver for the hardware monitoring and power management timer 
+ * in the VIA VT82C686A and VT8231 South Bridges.
+ */
 
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: viaenv.c,v 1.17 2006/11/16 01:33:10 christos Exp $");
@@ -40,22 +43,22 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/ioctl.h>
-#include <sys/kthread.h>
-#include <sys/lock.h>
-#include <sys/errno.h>
 #include <sys/device.h>
 
+#ifdef __HAVE_TIMECOUNTER
+#include <machine/bus.h>
+#include <dev/ic/acpipmtimer.h>
+#endif
+
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
-
-#include <dev/pci/viapmvar.h>
+#include <dev/pci/pcidevs.h>
 
 #include <dev/sysmon/sysmonvar.h>
 
 #ifdef VIAENV_DEBUG
 unsigned int viaenv_debug = 0;
-#define DPRINTF(X) do { if(viaenv_debug) printf X ; } while(0)
+#define DPRINTF(X) do { if (viaenv_debug) printf X ; } while(0)
 #else
 #define DPRINTF(X)
 #endif
@@ -66,11 +69,12 @@
 	struct device sc_dev;
 	bus_space_tag_t sc_iot;
 	bus_space_handle_t sc_ioh;
+	bus_space_handle_t sc_pm_ioh;
 
 	int     sc_fan_div[2];	/* fan RPM divisor */
 
-	struct envsys_tre_data sc_data[VIANUMSENSORS];
-	struct envsys_basic_info sc_info[VIANUMSENSORS];
+	envsys_tre_data_t sc_data[VIANUMSENSORS];
+	envsys_basic_info_t sc_info[VIANUMSENSORS];
 
 	struct simplelock sc_slock;
 	struct timeval sc_lastread;
@@ -88,20 +92,36 @@
 	{ 1, 0,		ENVSYS_SAMPS },		/* none */
 };
 
-static int	viaenv_gtredata(struct sysmon_envsys *,
-				struct envsys_tre_data *);
-static int 	viaenv_streinfo(struct sysmon_envsys *,
-				struct envsys_basic_info *);
+/* autoconf(9) glue */
+static int viaenv_match(struct device *, struct cfdata *, void *);
+static void viaenv_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(viaenv, sizeof(struct viaenv_softc),
+    viaenv_match, viaenv_attach, NULL, NULL);
+
+/* envsys(4) glue */
+static int viaenv_gtredata(struct sysmon_envsys *, envsys_tre_data_t *);
+static int viaenv_streinfo(struct sysmon_envsys *, envsys_basic_info_t *);
+
+static int val_to_uK(unsigned int);
+static int val_to_rpm(unsigned int, int);
+static long val_to_uV(unsigned int, int);
 
 static int
-viaenv_match(struct device *parent, struct cfdata *match,
-    void *aux)
+viaenv_match(struct device *parent, struct cfdata *match, void *aux)
 {
-	struct viapm_attach_args *va = aux;
+	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
 
-	if (va->va_type == VIAPM_HWMON)
+	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH)
+		return 0;
+
+	switch (PCI_PRODUCT(pa->pa_id)) {
+	case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
+	case PCI_PRODUCT_VIATECH_VT8231_PWR:
 		return 1;
-	return 0;
+	default:
+		return 0;
+	}
 }
 
 /*
@@ -198,13 +218,21 @@
 #define VIAENV_TLOW	0x49	/* temperature low order value */
 #define VIAENV_TIRQ	0x4b	/* temperature interrupt configuration */
 
+#define VIAENV_GENCFG	0x40	/* general configuration */
+#define VIAENV_GENCFG_TMR32	(1 << 11)	/* 32-bit PM timer */
+#define VIAENV_GENCFG_PMEN	(1 << 15)	/* enable PM I/O space */
+#define VIAENV_PMBASE	0x48	/* power management I/O space base */
+#define VIAENV_PMSIZE	128	/* HWM and power management I/O space size */
+#define VIAENV_PM_TMR	0x08	/* PM timer */
+#define VIAENV_HWMON_CONF	0x70	/* HWMon I/O base */
+#define VIAENV_HWMON_CTL	0x74	/* HWMon control register */
 
 static void
 viaenv_refresh_sensor_data(struct viaenv_softc *sc)
 {
 	static const struct timeval onepointfive =  { 1, 500000 };
 	struct timeval t, utv;
-	u_int8_t v, v2;
+	uint8_t v, v2;
 	int i;
 
 	/* Read new values at most once every 1.5 seconds. */
@@ -267,30 +295,44 @@
 static void
 viaenv_attach(struct device *parent, struct device *self, void *aux)
 {
-	struct viapm_attach_args *va = aux;
-	struct viaenv_softc *sc = (struct viaenv_softc *) self;
+	struct viaenv_softc *sc = (struct viaenv_softc *)self;
+	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
 	pcireg_t iobase, control;
 	int i;
 
-	iobase = pci_conf_read(va->va_pc, va->va_tag, va->va_offset);
-	if ((iobase & 0xff80) == 0) {
-		printf(": disabled\n");
-		return;
+	aprint_naive("\n");
+	aprint_normal(": VIA Technologies ");
+	switch (PCI_PRODUCT(pa->pa_id)) {
+	case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
+		aprint_normal("VT82C686A Hardware Monitor\n");
+		break;
+	case PCI_PRODUCT_VIATECH_VT8231_PWR:
+		aprint_normal("VT8231 Hardware Monitor\n");
+		break;
+	default:
+		aprint_normal("Unknown Hardware Monitor\n");
+		break;
 	}
-	control = pci_conf_read(va->va_pc, va->va_tag, va->va_offset + 4);
-	/* If the device is disabled, turn it on */
-	if ((control & 1) == 0)
-		pci_conf_write(va->va_pc, va->va_tag, va->va_offset + 4,
-		    control | 1);
-
-	sc->sc_iot = va->va_iot;
-	if (bus_space_map(sc->sc_iot, iobase & 0xff80, 128, 0, &sc->sc_ioh)) {
-		printf(": failed to map i/o\n");
-		return;
+
+	iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_HWMON_CONF);
+	DPRINTF(("%s: iobase 0x%x\n", sc->sc_dev.dv_xname, iobase));
+	control = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_HWMON_CTL);
+
+	/* Check if the Hardware Monitor enable bit is set */
+	if ((control & 1) == 0) {
+		aprint_normal("%s : Hardware Monitor disabled\n",
+		    sc->sc_dev.dv_xname);
+		goto nohwm;
 	}
-	printf("\n");
 
-	simple_lock_init(&sc->sc_slock);
+	/* Map Hardware Monitor I/O space */
+	sc->sc_iot = pa->pa_iot;
+	if (bus_space_map(sc->sc_iot, iobase & 0xff80,
+	    VIAENV_PMSIZE, 0, &sc->sc_ioh)) {
+		aprint_error("%s: failed to map I/O space\n",
+		    sc->sc_dev.dv_xname);
+		goto nohwm;
+	}
 
 	/* Initialize sensors */
 	for (i = 0; i < VIANUMSENSORS; ++i) {
@@ -300,33 +342,38 @@
 		sc->sc_data[i].warnflags = ENVSYS_WARN_OK;
 	}
 
-	for (i = 0; i <= 2; i++) {
+	for (i = 0; i <= 2; i++)
 		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_STEMP;
-	}
-	strcpy(sc->sc_info[0].desc, "TSENS1");
-	strcpy(sc->sc_info[1].desc, "TSENS2");
-	strcpy(sc->sc_info[2].desc, "TSENS3");
 
-	for (i = 3; i <= 4; i++) {
-		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_SFANRPM;
-	}
-	strcpy(sc->sc_info[3].desc, "FAN1");
-	strcpy(sc->sc_info[4].desc, "FAN2");
+#define COPYDESCR(x, y) 				\
+	do {						\
+		strlcpy((x), (y), sizeof(x));		\
+	} while (0)
+
+	COPYDESCR(sc->sc_info[0].desc, "TSENS1");
+	COPYDESCR(sc->sc_info[1].desc, "TSENS2");
+	COPYDESCR(sc->sc_info[2].desc, "TSENS3");
 
-	for (i = 5; i <= 9; ++i) {
-		sc->sc_data[i].units = sc->sc_info[i].units =
-		    ENVSYS_SVOLTS_DC;
-		sc->sc_info[i].rfact = 1;	/* what is this used for? */
-	}
-	strcpy(sc->sc_info[5].desc, "VSENS1");	/* CPU core (2V) */
-	strcpy(sc->sc_info[6].desc, "VSENS2");	/* NB core? (2.5V) */
-	strcpy(sc->sc_info[7].desc, "Vcore");	/* Vcore (3.3V) */
-	strcpy(sc->sc_info[8].desc, "VSENS3");	/* VSENS3 (5V) */
-	strcpy(sc->sc_info[9].desc, "VSENS4");	/* VSENS4 (12V) */
+	for (i = 3; i <= 4; i++)
+		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_SFANRPM;
+	
+	COPYDESCR(sc->sc_info[3].desc, "FAN1");
+	COPYDESCR(sc->sc_info[4].desc, "FAN2");
+
+	for (i = 5; i <= 9; ++i)
+		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_SVOLTS_DC;
+
+	COPYDESCR(sc->sc_info[5].desc, "VSENS1");	/* CPU core (2V) */
+	COPYDESCR(sc->sc_info[6].desc, "VSENS2");	/* NB core? (2.5V) */
+	COPYDESCR(sc->sc_info[7].desc, "Vcore");	/* Vcore (3.3V) */
+	COPYDESCR(sc->sc_info[8].desc, "VSENS3");	/* VSENS3 (5V) */
+	COPYDESCR(sc->sc_info[9].desc, "VSENS4");	/* VSENS4 (12V) */
 
 	/* Get initial set of sensor values. */
 	viaenv_refresh_sensor_data(sc);
 
+#undef COPYDESCR
+
 	/*
 	 * Hook into the System Monitor.
 	 */
@@ -344,13 +391,39 @@
 	if (sysmon_envsys_register(&sc->sc_sysmon))
 		printf("%s: unable to register with sysmon\n",
 		    sc->sc_dev.dv_xname);
-}
 
-CFATTACH_DECL(viaenv, sizeof(struct viaenv_softc),
-    viaenv_match, viaenv_attach, NULL, NULL);
+nohwm:
+#ifdef __HAVE_TIMECOUNTER
+	/* Check if power management I/O space is enabled */
+	control = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_GENCFG);
+	if ((control & VIAENV_GENCFG_PMEN) == 0) {
+                aprint_normal("%s: Power Managament controller disabled\n",
+		    sc->sc_dev.dv_xname);
+                goto nopm;
+        }
+
+        /* Map power management I/O space */
+        iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_PMBASE);
+        if (bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(iobase),
+            VIAENV_PMSIZE, 0, &sc->sc_pm_ioh)) {
+                aprint_error("%s: failed to map PM I/O space\n",
+		    sc->sc_dev.dv_xname);
+                goto nopm;
+        }
+
+	/* Attach our PM timer with the generic acpipmtimer function */
+	acpipmtimer_attach(&sc->sc_dev, sc->sc_iot, sc->sc_pm_ioh,
+	    VIAENV_PM_TMR,
+	    ((control & VIAENV_GENCFG_TMR32) ? ACPIPMT_32BIT : 0));
+
+nopm:
+#endif /* __HAVE_TIMECOUNTER */
+	/*XXX Avoid label at end of compound */
+	return;
+}
 
 static int
-viaenv_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
+viaenv_gtredata(struct sysmon_envsys *sme, envsys_tre_data_t *tred)
 {
 	struct viaenv_softc *sc = sme->sme_cookie;
 
@@ -361,16 +434,14 @@
 
 	simple_unlock(&sc->sc_slock);
 
-	return (0);
+	return 0;
 }
 
 static int
-viaenv_streinfo(struct sysmon_envsys *sme,
-    struct envsys_basic_info *binfo)
+viaenv_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
 {
-
-	/* XXX Not implemented */
+	/* Not implemented */
 	binfo->validflags = 0;
 
-	return (0);
+	return 0;
 }

--Qxx1br4bt0+wmkIi--