diff options
author | 2012-05-27 12:24:33 +0000 | |
---|---|---|
committer | 2012-05-27 12:24:33 +0000 | |
commit | f6ad04e698374600abe223ff91ba36f2bb7b03d3 (patch) | |
tree | 105279f60fbffae79d08966206e106c2e6c98072 | |
parent | Use an en-dash for 20-200, escape - used as arithmetic symbol. (diff) | |
download | wireguard-openbsd-f6ad04e698374600abe223ff91ba36f2bb7b03d3.tar.xz wireguard-openbsd-f6ad04e698374600abe223ff91ba36f2bb7b03d3.zip |
Add tcpcib(4) to support Intel Atom E600 watchdog.
From Matt Dainty. ok kettenis@
-rw-r--r-- | share/man/man4/man4.amd64/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/man4.amd64/tcpcib.4 | 64 | ||||
-rw-r--r-- | share/man/man4/man4.i386/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/man4.i386/tcpcib.4 | 64 | ||||
-rw-r--r-- | sys/arch/amd64/conf/files.amd64 | 9 | ||||
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 9 | ||||
-rw-r--r-- | sys/dev/pci/tcpcib.c | 269 |
7 files changed, 415 insertions, 8 deletions
diff --git a/share/man/man4/man4.amd64/Makefile b/share/man/man4/man4.amd64/Makefile index 94bae82fd86..ae24f06c785 100644 --- a/share/man/man4/man4.amd64/Makefile +++ b/share/man/man4/man4.amd64/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.14 2011/03/18 12:40:29 deraadt Exp $ +# $OpenBSD: Makefile,v 1.15 2012/05/27 12:24:33 jsg Exp $ MAN= amdpcib.4 apm.4 autoconf.4 bios.4 cpu.4 intro.4 ioapic.4 \ - mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 + mem.4 mpbios.4 nvram.4 mtrr.4 pctr.4 tcpcib.4 MLINKS+= mem.4 kmem.4 MANSUBDIR=amd64 diff --git a/share/man/man4/man4.amd64/tcpcib.4 b/share/man/man4/man4.amd64/tcpcib.4 new file mode 100644 index 00000000000..9e9572c2bf7 --- /dev/null +++ b/share/man/man4/man4.amd64/tcpcib.4 @@ -0,0 +1,64 @@ +.\" $OpenBSD: tcpcib.4,v 1.1 2012/05/27 12:24:33 jsg Exp $ +.\" +.\" Copyright (c) 2012 Matt Dainty <matt@bodgit-n-scarper.com> +.\" +.\" 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. +.\" +.Dd $Mdocdate: May 27 2012 $ +.Dt TCPCIB 4 amd64 +.Os +.Sh NAME +.Nm tcpcib +.Nd Intel Atom E600 series LPC bridge and watchdog +.Sh SYNOPSIS +.Cd "tcpcib* at pci?" +.Cd "isa* at tcpcib?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the Intel Atom E600 series LPC bridge and +provides the standard +.Xr watchdog 4 +interface to the watchdog timer and may be used with +.Xr watchdogd 8 . +The watchdog timer can be configured via +.Xr sysctl 8 . +.Pp +Once the watchdog timer resets the CPU, the driver reports it on the +next boot displaying the ``reboot on timeout'' message in the dmesg. +.Sh NOTES +The maximum timeout value supported by the watchdog timer is 600 +seconds. +.Sh SEE ALSO +.Xr intro 4 , +.Xr isa 4 , +.Xr pci 4 , +.Xr watchdog 4 +.Xr sysctl 8 +.Xr watchdogd 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 5.2 . +.Sh AUTHORS +The +.Nm +driver was written by +.An Matt Dainty Aq matt@bodgit-n-scarper.com . +.Sh BUGS +Apart from the core +.Xr pcib 4 +functionality and the +.Xr watchdog 4 +interface, the driver doesn't support any other aspects of the hardware. diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile index b20ae9adfe3..5d315619ecc 100644 --- a/share/man/man4/man4.i386/Makefile +++ b/share/man/man4/man4.i386/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.71 2011/06/29 17:49:39 tedu Exp $ +# $OpenBSD: Makefile,v 1.72 2012/05/27 12:24:33 jsg Exp $ # from: @(#)Makefile 5.1 (Berkeley) 2/12/91 # Id: Makefile,v 1.4 1995/12/14 05:41:38 deraadt Exp $ @@ -7,7 +7,7 @@ MAN= amdpcib.4 amdmsr.4 apm.4 autoconf.4 bios.4 cpu.4 elansc.4 \ ichpcib.4 intro.4 ioapic.4 \ joy.4 le.4 lms.4 mem.4 mms.4 mpbios.4 mtrr.4 npx.4 nvram.4 \ pas.4 pcibios.4 pctr.4 piixpcib.4 sb.4 \ - sea.4 uha.4 wds.4 wdt.4 wss.4 + sea.4 tcpcib.4 uha.4 wds.4 wdt.4 wss.4 MLINKS+= mem.4 kmem.4 MANSUBDIR=i386 diff --git a/share/man/man4/man4.i386/tcpcib.4 b/share/man/man4/man4.i386/tcpcib.4 new file mode 100644 index 00000000000..20f5d248569 --- /dev/null +++ b/share/man/man4/man4.i386/tcpcib.4 @@ -0,0 +1,64 @@ +.\" $OpenBSD: tcpcib.4,v 1.1 2012/05/27 12:24:33 jsg Exp $ +.\" +.\" Copyright (c) 2012 Matt Dainty <matt@bodgit-n-scarper.com> +.\" +.\" 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. +.\" +.Dd $Mdocdate: May 27 2012 $ +.Dt TCPCIB 4 i386 +.Os +.Sh NAME +.Nm tcpcib +.Nd Intel Atom E600 series LPC bridge and watchdog +.Sh SYNOPSIS +.Cd "tcpcib* at pci?" +.Cd "isa* at tcpcib?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the Intel Atom E600 series LPC bridge and +provides the standard +.Xr watchdog 4 +interface to the watchdog timer and may be used with +.Xr watchdogd 8 . +The watchdog timer can be configured via +.Xr sysctl 8 . +.Pp +Once the watchdog timer resets the CPU, the driver reports it on the +next boot displaying the ``reboot on timeout'' message in the dmesg. +.Sh NOTES +The maximum timeout value supported by the watchdog timer is 600 +seconds. +.Sh SEE ALSO +.Xr intro 4 , +.Xr isa 4 , +.Xr pci 4 , +.Xr watchdog 4 +.Xr sysctl 8 +.Xr watchdogd 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 5.2 . +.Sh AUTHORS +The +.Nm +driver was written by +.An Matt Dainty Aq matt@bodgit-n-scarper.com . +.Sh BUGS +Apart from the core +.Xr pcib 4 +functionality and the +.Xr watchdog 4 +interface, the driver doesn't support any other aspects of the hardware. diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index f7ec52acd39..6ddd2da0205 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.amd64,v 1.66 2011/11/15 22:27:52 deraadt Exp $ +# $OpenBSD: files.amd64,v 1.67 2012/05/27 12:24:33 jsg Exp $ maxpartitions 16 maxusers 2 16 128 @@ -147,13 +147,18 @@ include "dev/pcmcia/files.pcmcia" # PCI-ISA bridges device pcib: isabus attach pcib at pci -file arch/amd64/pci/pcib.c pcib | amdpcib +file arch/amd64/pci/pcib.c pcib | amdpcib | tcpcib # AMD 8111 LPC bridge device amdpcib: isabus attach amdpcib at pci file dev/pci/amdpcib.c amdpcib +# Intel Atom E600 LPC bridge +device tcpcib: isabus +attach tcpcib at pci +file dev/pci/tcpcib.c tcpcib + device aapic attach aapic at pci file arch/amd64/pci/aapic.c aapic diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 01e2ae4b025..5755aee064f 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.209 2011/11/15 22:27:52 deraadt Exp $ +# $OpenBSD: files.i386,v 1.210 2012/05/27 12:24:33 jsg Exp $ # # new style config file for i386 architecture # @@ -147,7 +147,7 @@ file arch/i386/i386/amdmsr.c amdmsr needs-flag # PCI-ISA bridge chipsets device pcib: isabus attach pcib at pci -file arch/i386/pci/pcib.c pcib | ichpcib | gscpcib | glxpcib | piixpcib | amdpcib +file arch/i386/pci/pcib.c pcib | ichpcib | gscpcib | glxpcib | piixpcib | amdpcib | tcpcib # Intel ICHx/ICHx-M LPC bridges device ichpcib: isabus @@ -169,6 +169,11 @@ device amdpcib: isabus attach amdpcib at pci file dev/pci/amdpcib.c amdpcib +# Intel Atom E600 LPC bridge +device tcpcib: isabus +attach tcpcib at pci +file dev/pci/tcpcib.c tcpcib + device hme: ether, ifnet, mii, ifmedia file dev/ic/hme.c hme attach hme at pci with hme_pci diff --git a/sys/dev/pci/tcpcib.c b/sys/dev/pci/tcpcib.c new file mode 100644 index 00000000000..5cae998de72 --- /dev/null +++ b/sys/dev/pci/tcpcib.c @@ -0,0 +1,269 @@ +/* $OpenBSD: tcpcib.c,v 1.1 2012/05/27 12:24:33 jsg Exp $ */ + +/* + * Copyright (c) 2012 Matt Dainty <matt@bodgit-n-scarper.com> + * + * 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 MIND, 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. + */ + +/* + * Intel Atom E600 series LPC bridge also containing watchdog + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#define E600_LPC_SMBA 0x40 /* SMBus Base Address */ +#define E600_LPC_GBA 0x44 /* GPIO Base Address */ +#define E600_LPC_WDTBA 0x84 /* WDT Base Address */ + +#define E600_WDT_SIZE 64 /* I/O region size */ +#define E600_WDT_PV1 0x00 /* Preload Value 1 Register */ +#define E600_WDT_PV2 0x04 /* Preload Value 2 Register */ +#define E600_WDT_RR0 0x0c /* Reload Register 0 */ +#define E600_WDT_RR1 0x0d /* Reload Register 1 */ +#define E600_WDT_RR1_RELOAD (1 << 0) /* WDT Reload Flag */ +#define E600_WDT_RR1_TIMEOUT (1 << 1) /* WDT Timeout Flag */ +#define E600_WDT_WDTCR 0x10 /* WDT Configuration Register */ +#define E600_WDT_WDTCR_PRE (1 << 2) /* WDT Prescalar Select */ +#define E600_WDT_WDTCR_RESET (1 << 3) /* WDT Reset Select */ +#define E600_WDT_WDTCR_ENABLE (1 << 4) /* WDT Reset Enable */ +#define E600_WDT_WDTCR_TIMEOUT (1 << 5) /* WDT Timeout Output Enable */ +#define E600_WDT_DCR 0x14 /* Down Counter Register */ +#define E600_WDT_WDTLR 0x18 /* WDT Lock Register */ +#define E600_WDT_WDTLR_LOCK (1 << 0) /* Watchdog Timer Lock */ +#define E600_WDT_WDTLR_ENABLE (1 << 1) /* Watchdog Timer Enable */ +#define E600_WDT_WDTLR_TIMEOUT (1 << 2) /* WDT Timeout Configuration */ + +struct tcpcib_softc { + struct device sc_dev; + + /* Keep track of which parts of the hardware are active */ + int sc_active; +#define E600_WDT_ACTIVE (1 << 0) + + /* Watchdog interface */ + bus_space_tag_t sc_wdt_iot; + bus_space_handle_t sc_wdt_ioh; + + int sc_wdt_period; +}; + +struct cfdriver tcpcib_cd = { + NULL, "tcpcib", DV_DULL +}; + +int tcpcib_match(struct device *, void *, void *); +void tcpcib_attach(struct device *, struct device *, void *); +int tcpcib_activate(struct device *, int); + +int tcpcib_wdt_cb(void *, int); +void tcpcib_wdt_init(struct tcpcib_softc *, int); +void tcpcib_wdt_start(struct tcpcib_softc *); +void tcpcib_wdt_stop(struct tcpcib_softc *); + +struct cfattach tcpcib_ca = { + sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach, + NULL, tcpcib_activate +}; + +/* from arch/<*>/pci/pcib.c */ +void pcibattach(struct device *parent, struct device *self, void *aux); + +const struct pci_matchid tcpcib_devices[] = { + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_E600_LPC } +}; + +static __inline void +tcpcib_wdt_unlock(struct tcpcib_softc *sc) +{ + /* Register unlocking sequence */ + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR0, 0x80); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR0, 0x86); +} + +void +tcpcib_wdt_init(struct tcpcib_softc *sc, int period) +{ + u_int32_t preload; + + /* Set new timeout */ + preload = (period * 33000000) >> 15; + preload--; + + /* + * Set watchdog to perform a cold reset toggling the GPIO pin and the + * prescaler set to 1ms-10m resolution + */ + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTCR, + E600_WDT_WDTCR_ENABLE); + tcpcib_wdt_unlock(sc); + bus_space_write_4(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_PV1, 0); + tcpcib_wdt_unlock(sc); + bus_space_write_4(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_PV2, + preload); + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1, + E600_WDT_RR1_RELOAD); +} + +void +tcpcib_wdt_start(struct tcpcib_softc *sc) +{ + /* Enable watchdog */ + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTLR, + E600_WDT_WDTLR_ENABLE); +} + +void +tcpcib_wdt_stop(struct tcpcib_softc *sc) +{ + /* Disable watchdog, with a reload before for safety */ + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1, + E600_WDT_RR1_RELOAD); + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTLR, 0); +} + +int +tcpcib_match(struct device *parent, void *match, void *aux) +{ + if (pci_matchbyid((struct pci_attach_args *)aux, tcpcib_devices, + sizeof(tcpcib_devices) / sizeof(tcpcib_devices[0]))) + return (2); + + return (0); +} + +void +tcpcib_attach(struct device *parent, struct device *self, void *aux) +{ + struct tcpcib_softc *sc = (struct tcpcib_softc *)self; + struct pci_attach_args *pa = aux; + u_int32_t reg, wdtbase; + + sc->sc_active = 0; + + /* Map Watchdog I/O space */ + reg = pci_conf_read(pa->pa_pc, pa->pa_tag, E600_LPC_WDTBA); + wdtbase = reg & 0xffff; + sc->sc_wdt_iot = pa->pa_iot; + if (reg & (1 << 31) && wdtbase) { + if (PCI_MAPREG_IO_ADDR(wdtbase) == 0 || + bus_space_map(sc->sc_wdt_iot, PCI_MAPREG_IO_ADDR(wdtbase), + E600_WDT_SIZE, 0, &sc->sc_wdt_ioh)) { + printf(": can't map watchdog I/O space"); + goto corepcib; + } + printf(": watchdog"); + + /* Check for reboot on timeout */ + reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, + E600_WDT_RR1); + if (reg & E600_WDT_RR1_TIMEOUT) { + printf(", reboot on timeout"); + + /* Clear timeout bit */ + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, + E600_WDT_RR1, E600_WDT_RR1_TIMEOUT); + } + + /* Check it's not locked already */ + reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, + E600_WDT_WDTLR); + if (reg & E600_WDT_WDTLR_LOCK) { + printf(", locked"); + goto corepcib; + } + + /* Disable watchdog */ + tcpcib_wdt_stop(sc); + sc->sc_wdt_period = 0; + + sc->sc_active |= E600_WDT_ACTIVE; + + /* Register new watchdog */ + wdog_register(sc, tcpcib_wdt_cb); + } + +corepcib: + /* Provide core pcib(4) functionality */ + pcibattach(parent, self, aux); +} + +int +tcpcib_activate(struct device *self, int act) +{ + struct tcpcib_softc *sc = (struct tcpcib_softc *)self; + + switch (act) { + case DVACT_SUSPEND: + /* Watchdog is running, disable it */ + if (sc->sc_active & E600_WDT_ACTIVE && sc->sc_wdt_period != 0) + tcpcib_wdt_stop(sc); + break; + case DVACT_RESUME: + if (sc->sc_active & E600_WDT_ACTIVE) { + /* + * Watchdog was running prior to suspend so reenable + * it, otherwise make sure it stays disabled + */ + if (sc->sc_wdt_period != 0) { + tcpcib_wdt_init(sc, sc->sc_wdt_period); + tcpcib_wdt_start(sc); + } else + tcpcib_wdt_stop(sc); + } + break; + } + return (0); +} + +int +tcpcib_wdt_cb(void *arg, int period) +{ + struct tcpcib_softc *sc = arg; + + if (period == 0) { + if (sc->sc_wdt_period != 0) + tcpcib_wdt_stop(sc); + } else { + /* 600 seconds is the maximum supported timeout value */ + if (period > 600) + period = 600; + if (sc->sc_wdt_period != period) + tcpcib_wdt_init(sc, period); + if (sc->sc_wdt_period == 0) { + tcpcib_wdt_start(sc); + } else { + /* Reset timer */ + tcpcib_wdt_unlock(sc); + bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, + E600_WDT_RR1, E600_WDT_RR1_RELOAD); + } + } + sc->sc_wdt_period = period; + + return (period); +} |