Subject: amd8111 LPC watchdog support
To: None <port-amd64@netbsd.org>
From: Joerg Sonnenberger <joerg@britannica.bec.de>
List: port-amd64
Date: 11/24/2007 18:55:35
--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi all,
I hope someone here has a AMD8111 LPC bridge to test the attached patch.
E.g. pcictl pci0 list will tell you. If you have, please apply the patch
to -current, uncomment the amdpcib* entry in GENERIC and run
	wdogctl -k -p1 amdpcib0
after reboot. System should continue to run. Now enter DDB and after a
second, the system should reboot.

Joerg

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="amdpcib.c.diff"

Index: amdpcib.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/x86/pci/amdpcib.c,v
retrieving revision 1.1
diff -u -p -r1.1 amdpcib.c
--- amdpcib.c	26 Oct 2007 22:17:14 -0000	1.1
+++ amdpcib.c	23 Nov 2007 00:35:06 -0000
@@ -31,6 +31,7 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: amdpcib.c,v 1.1 2007/10/26 22:17:14 xtraeme Exp $");
 
+#include <sys/errno.h>
 #include <sys/systm.h>
 #include <sys/device.h>
 
@@ -38,17 +39,27 @@ __KERNEL_RCSID(0, "$NetBSD: amdpcib.c,v 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcidevs.h>
 
+#include <dev/sysmon/sysmonvar.h>
+
 struct amdpcib_softc {
 	struct device		sc_dev;
 
 	bus_space_tag_t		sc_memt;
 	bus_space_handle_t	sc_memh;
+
+	struct sysmon_wdog	sc_smw;
+	bus_space_tag_t		sc_wdog_tag;
+	bus_space_handle_t	sc_wdog_handle;
 };
 
 static int	amdpcib_match(struct device *, struct cfdata *, void *);
 static void	amdpcib_attach(struct device *, struct device *, void *);
 static int	amdpcib_search(device_t, cfdata_t, const int *, void *);
 
+static void	amdpcib_wdog_stop(struct amdpcib_softc *);
+static int	amdpcib_wdog_setmode(struct sysmon_wdog *);
+static int	amdpcib_wdog_tickle(struct sysmon_wdog *);
+
 
 extern void	pcibattach(struct device *, struct device *, void *);
 
@@ -72,6 +83,8 @@ amdpcib_attach(struct device *parent, st
 {
 	struct amdpcib_softc *sc;
 	struct pci_attach_args *pa;
+	bus_addr_t wdog_addr;
+	pcireg_t reg;
 
 	sc = (struct amdpcib_softc *)self;
 	pa = (struct pci_attach_args *)aux;
@@ -79,6 +92,31 @@ amdpcib_attach(struct device *parent, st
 	pcibattach(parent, self, aux);
 
 	config_search_loc(amdpcib_search, &sc->sc_dev, "amdpcib", NULL, pa);
+
+	sc->sc_wdog_tag = X86_BUS_SPACE_MEM;
+	/* Map 32 byte below 4GB */
+	bus_space_alloc(sc->sc_wdog_tag, 0, 0xffffffff, 32, 32, 0, 0,
+	    &wdog_addr, &sc->sc_wdog_handle);
+
+	/* Enable address range decoding with disabled watchdog first */
+	reg = (uint32_t)wdog_addr | 1;
+	pci_conf_write(pa->pa_pc, pa->pa_tag, 0xa8, reg | 2);
+	/* Ensure that the watchdog is stopped */
+	amdpcib_wdog_stop(sc);
+	/* ...and enable the watchdog processing */
+	pci_conf_write(pa->pa_pc, pa->pa_tag, 0xa8, reg);
+
+	sc->sc_smw.smw_name = device_xname(self);
+	sc->sc_smw.smw_cookie = sc;
+	sc->sc_smw.smw_setmode = amdpcib_wdog_setmode;
+	sc->sc_smw.smw_tickle = amdpcib_wdog_tickle;
+	sc->sc_smw.smw_period = 0xffff;
+
+	if (sysmon_wdog_register(&sc->sc_smw)) {
+		aprint_error_dev(self, "unable to watchdog timer.\n");
+		return;
+	}
+
 }
 
 static int
@@ -90,3 +128,37 @@ amdpcib_search(device_t parent, cfdata_t
 
 	return 0;
 }
+
+static void
+amdpcib_wdog_stop(struct amdpcib_softc *sc)
+{
+	bus_space_write_4(sc->sc_wdog_tag, sc->sc_wdog_handle, 8, 0);
+}
+
+static int
+amdpcib_wdog_setmode(struct sysmon_wdog *smw)
+{
+	struct amdpcib_softc *sc = smw->smw_cookie;
+
+	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
+		amdpcib_wdog_stop(sc);
+		return 0;
+	}
+
+	if (smw->smw_period > 0xffff)
+		return EINVAL;
+
+	amdpcib_wdog_stop(sc);
+	bus_space_write_4(sc->sc_wdog_tag, sc->sc_wdog_handle, 0, smw->smw_period);
+	amdpcib_wdog_tickle(smw);
+	return 0;
+}
+
+static int
+amdpcib_wdog_tickle(struct sysmon_wdog *smw)
+{
+	struct amdpcib_softc *sc = smw->smw_cookie;
+
+	bus_space_write_4(sc->sc_wdog_tag, sc->sc_wdog_handle, 8, 0x81);
+	return 0;
+}

--FCuugMFkClbJLl1L--