summaryrefslogtreecommitdiffstats
path: root/sys/dev/ichwd
diff options
context:
space:
mode:
authorambrisko <ambrisko@FreeBSD.org>2006-02-17 18:46:18 +0000
committerambrisko <ambrisko@FreeBSD.org>2006-02-17 18:46:18 +0000
commit735f0011159914d170f7397dca841aceeeebe091 (patch)
tree9ba4a79a3a3d2adc4f72791e42c2d32f02d54d1b /sys/dev/ichwd
parent3cf2c022c26b2a90b7581da1688722843d1e77ab (diff)
downloadFreeBSD-src-735f0011159914d170f7397dca841aceeeebe091.zip
FreeBSD-src-735f0011159914d170f7397dca841aceeeebe091.tar.gz
Re-work the bus attachment somewhat. Make the rids unique for
the SMI/TCO address space. Switch the bus space I/O to the one specific for either the SMI or TCO space. Re-calibrate the tick. Add some more device id's, 82801FBR submitted by des. This makes it work on the platforms I've tested with. Go ahead by: des
Diffstat (limited to 'sys/dev/ichwd')
-rw-r--r--sys/dev/ichwd/ichwd.c83
-rw-r--r--sys/dev/ichwd/ichwd.h5
2 files changed, 51 insertions, 37 deletions
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index 893efbd..8ddeb8c 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -81,43 +81,51 @@ static struct ichwd_device ichwd_devices[] = {
{ VENDORID_INTEL, DEVICEID_82801DBM, "Intel 82801DBM watchdog timer" },
{ VENDORID_INTEL, DEVICEID_82801E, "Intel 82801E watchdog timer" },
{ VENDORID_INTEL, DEVICEID_82801EBR, "Intel 82801EB/ER watchdog timer" },
+ { VENDORID_INTEL, DEVICEID_82801FBR, "Intel 82801FB/FR watchdog timer" },
+ { VENDORID_INTEL, DEVICEID_ICH5, "Intel ICH5 watchdog timer"},
+ { VENDORID_INTEL, DEVICEID_6300ESB, "Intel 6300ESB watchdog timer"},
{ 0, 0, NULL },
};
static devclass_t ichwd_devclass;
-#define ichwd_read_1(sc, off) \
- bus_space_read_1((sc)->smi_bst, (sc)->smi_bsh, (off))
-#define ichwd_read_2(sc, off) \
- bus_space_read_2((sc)->smi_bst, (sc)->smi_bsh, (off))
-#define ichwd_read_4(sc, off) \
+#define ichwd_read_tco_1(sc, off) \
+ bus_space_read_1((sc)->tco_bst, (sc)->tco_bsh, (off))
+#define ichwd_read_tco_2(sc, off) \
+ bus_space_read_2((sc)->tco_bst, (sc)->tco_bsh, (off))
+#define ichwd_read_tco_4(sc, off) \
+ bus_space_read_4((sc)->tco_bst, (sc)->tco_bsh, (off))
+
+#define ichwd_write_tco_1(sc, off, val) \
+ bus_space_write_1((sc)->tco_bst, (sc)->tco_bsh, (off), (val))
+#define ichwd_write_tco_2(sc, off, val) \
+ bus_space_write_2((sc)->tco_bst, (sc)->tco_bsh, (off), (val))
+#define ichwd_write_tco_4(sc, off, val) \
+ bus_space_write_4((sc)->tco_bst, (sc)->tco_bsh, (off), (val))
+
+#define ichwd_read_smi_4(sc, off) \
bus_space_read_4((sc)->smi_bst, (sc)->smi_bsh, (off))
-
-#define ichwd_write_1(sc, off, val) \
- bus_space_write_1((sc)->smi_bst, (sc)->smi_bsh, (off), (val))
-#define ichwd_write_2(sc, off, val) \
- bus_space_write_2((sc)->smi_bst, (sc)->smi_bsh, (off), (val))
-#define ichwd_write_4(sc, off, val) \
+#define ichwd_write_smi_4(sc, off, val) \
bus_space_write_4((sc)->smi_bst, (sc)->smi_bsh, (off), (val))
static __inline void
ichwd_intr_enable(struct ichwd_softc *sc)
{
- ichwd_write_4(sc, SMI_EN, ichwd_read_4(sc, SMI_EN) | SMI_TCO_EN);
+ ichwd_write_smi_4(sc, SMI_EN, ichwd_read_smi_4(sc, SMI_EN) & ~SMI_TCO_EN);
}
static __inline void
ichwd_intr_disable(struct ichwd_softc *sc)
{
- ichwd_write_4(sc, SMI_EN, ichwd_read_4(sc, SMI_EN) & ~SMI_TCO_EN);
+ ichwd_write_smi_4(sc, SMI_EN, ichwd_read_smi_4(sc, SMI_EN) | SMI_TCO_EN);
}
static __inline void
ichwd_sts_reset(struct ichwd_softc *sc)
{
- ichwd_write_2(sc, TCO1_STS, TCO_TIMEOUT);
- ichwd_write_2(sc, TCO2_STS, TCO_BOOT_STS);
- ichwd_write_2(sc, TCO2_STS, TCO_SECOND_TO_STS);
+ ichwd_write_tco_2(sc, TCO1_STS, TCO_TIMEOUT);
+ ichwd_write_tco_2(sc, TCO2_STS, TCO_BOOT_STS);
+ ichwd_write_tco_2(sc, TCO2_STS, TCO_SECOND_TO_STS);
}
static __inline void
@@ -125,8 +133,8 @@ ichwd_tmr_enable(struct ichwd_softc *sc)
{
uint16_t cnt;
- cnt = ichwd_read_2(sc, TCO1_CNT) & TCO_CNT_PRESERVE;
- ichwd_write_2(sc, TCO1_CNT, cnt & ~TCO_TMR_HALT);
+ cnt = ichwd_read_tco_2(sc, TCO1_CNT) & TCO_CNT_PRESERVE;
+ ichwd_write_tco_2(sc, TCO1_CNT, cnt & ~TCO_TMR_HALT);
sc->active = 1;
if (bootverbose)
device_printf(sc->device, "timer enabled\n");
@@ -137,8 +145,8 @@ ichwd_tmr_disable(struct ichwd_softc *sc)
{
uint16_t cnt;
- cnt = ichwd_read_2(sc, TCO1_CNT) & TCO_CNT_PRESERVE;
- ichwd_write_2(sc, TCO1_CNT, cnt | TCO_TMR_HALT);
+ cnt = ichwd_read_tco_2(sc, TCO1_CNT) & TCO_CNT_PRESERVE;
+ ichwd_write_tco_2(sc, TCO1_CNT, cnt | TCO_TMR_HALT);
sc->active = 0;
if (bootverbose)
device_printf(sc->device, "timer disabled\n");
@@ -147,7 +155,7 @@ ichwd_tmr_disable(struct ichwd_softc *sc)
static __inline void
ichwd_tmr_reload(struct ichwd_softc *sc)
{
- ichwd_write_1(sc, TCO_RLD, 1);
+ ichwd_write_tco_1(sc, TCO_RLD, 1);
if (bootverbose)
device_printf(sc->device, "timer reloaded\n");
}
@@ -155,7 +163,7 @@ ichwd_tmr_reload(struct ichwd_softc *sc)
static __inline void
ichwd_tmr_set(struct ichwd_softc *sc, uint8_t timeout)
{
- ichwd_write_1(sc, TCO_TMR, timeout);
+ ichwd_write_tco_1(sc, TCO_TMR, timeout);
sc->timeout = timeout;
if (bootverbose)
device_printf(sc->device, "timeout set to %u ticks\n", timeout);
@@ -170,10 +178,9 @@ ichwd_event(void *arg, unsigned int cmd, int *error)
struct ichwd_softc *sc = arg;
unsigned int timeout;
- cmd &= WD_INTERVAL;
/* disable / enable */
- if (cmd == 0) {
+ if (!(cmd & WD_ACTIVE)) {
if (sc->active)
ichwd_tmr_disable(sc);
*error = 0;
@@ -182,6 +189,7 @@ ichwd_event(void *arg, unsigned int cmd, int *error)
if (!sc->active)
ichwd_tmr_enable(sc);
+ cmd &= WD_INTERVAL;
/* convert from power-of-to-ns to WDT ticks */
if (cmd >= 64) {
*error = EINVAL;
@@ -204,7 +212,7 @@ ichwd_event(void *arg, unsigned int cmd, int *error)
return;
}
-static unsigned long pmbase;
+static unsigned int pmbase = 0;
/*
* Look for an ICH LPC interface bridge. If one is found, register an
@@ -268,27 +276,34 @@ ichwd_attach(device_t dev)
sc = device_get_softc(dev);
sc->device = dev;
+ if (pmbase == 0) {
+ printf("Not found\n");
+ }
+
/* allocate I/O register space */
+ sc->smi_rid = 0;
sc->smi_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->smi_rid,
- pmbase + SMI_BASE, pmbase + SMI_BASE + SMI_LEN - 1, SMI_LEN,
- RF_ACTIVE|RF_SHAREABLE);
+ pmbase + SMI_BASE, ~0ul, SMI_LEN,
+ RF_ACTIVE | RF_SHAREABLE);
if (sc->smi_res == NULL) {
device_printf(dev, "unable to reserve SMI registers\n");
goto fail;
}
sc->smi_bst = rman_get_bustag(sc->smi_res);
sc->smi_bsh = rman_get_bushandle(sc->smi_res);
+
+ sc->tco_rid = 1;
sc->tco_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->tco_rid,
- pmbase + TCO_BASE, pmbase + TCO_BASE + TCO_LEN - 1, TCO_LEN,
- RF_ACTIVE|RF_SHAREABLE);
+ pmbase + TCO_BASE, ~0ul, TCO_LEN,
+ RF_ACTIVE | RF_SHAREABLE);
if (sc->tco_res == NULL) {
device_printf(dev, "unable to reserve TCO registers\n");
goto fail;
}
sc->tco_bst = rman_get_bustag(sc->tco_res);
sc->tco_bsh = rman_get_bushandle(sc->tco_res);
-
/* reset the watchdog status registers */
+
ichwd_sts_reset(sc);
/* make sure the WDT starts out inactive */
@@ -348,6 +363,7 @@ static device_method_t ichwd_methods[] = {
DEVMETHOD(device_probe, ichwd_probe),
DEVMETHOD(device_attach, ichwd_attach),
DEVMETHOD(device_detach, ichwd_detach),
+ DEVMETHOD(device_shutdown, ichwd_detach),
{0,0}
};
@@ -376,9 +392,4 @@ ichwd_modevent(module_t mode, int type, void *data)
return (error);
}
-DRIVER_MODULE(ichwd, nexus, ichwd_driver, ichwd_devclass, ichwd_modevent, NULL);
-/*
- * this doesn't seem to work, though I can't figure out why.
- * currently not a big issue since watchdog is standard.
-MODULE_DEPEND(ichwd, watchdog, 1, 1, 1);
- */
+DRIVER_MODULE(ichwd, isa, ichwd_driver, ichwd_devclass, ichwd_modevent, NULL);
diff --git a/sys/dev/ichwd/ichwd.h b/sys/dev/ichwd/ichwd.h
index ef08b2f..ad66f9a 100644
--- a/sys/dev/ichwd/ichwd.h
+++ b/sys/dev/ichwd/ichwd.h
@@ -67,6 +67,9 @@ struct ichwd_softc {
#define DEVICEID_82801DBM 0x24cc
#define DEVICEID_82801E 0x2450
#define DEVICEID_82801EBR 0x24d0
+#define DEVICEID_6300ESB 0x25a1
+#define DEVICEID_82801FBR 0x2640
+#define DEVICEID_ICH5 0x27b8
/* ICH LPC Interface Bridge Registers */
#define ICH_GEN_STA 0xd4
@@ -110,7 +113,7 @@ struct ichwd_softc {
#define TCO_CNT_PRESERVE 0x0200 /* preserve these bits */
/* approximate length in nanoseconds of one WDT tick */
-#define ICHWD_TICK 600000000
+#define ICHWD_TICK 1800000000
/* minimum / maximum timeout in WDT ticks */
#define ICHWD_MIN_TIMEOUT 2
OpenPOWER on IntegriCloud