> Date: Sat, 2 Jun 2012 15:36:22 -0400
> From: Matt Dainty <[email protected]>
>
> As before but with the verbosity of the attach line tuned down a notch
> and not printing extra ':'s as pointed out by Theo. So now it looks
> like this:
>
> ---8<---
> tcpcib0 at pci0 dev 31 function 0 "Intel E600 LPC" rev 0x00: 14318179 Hz
> timer, watchdog
> ---8<---
>
> Matt
I've committed the part to remove the unecessary tcpcib_wdt_unlock()
calls, since it's better to have that committed as a seperate diff.
I'm looking at the HPET stuff now. Can you regenerate your diff and
post it here (after my commit has percolated to your anoncvs mirror)
for people who want to try it?
> --- sys/dev/pci/tcpcib.c.orig Wed May 30 12:19:41 2012
> +++ sys/dev/pci/tcpcib.c Wed May 30 16:21:13 2012
> @@ -17,12 +17,13 @@
> */
>
> /*
> - * Intel Atom E600 series LPC bridge also containing watchdog
> + * Intel Atom E600 series LPC bridge also containing HPET and watchdog
> */
>
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/device.h>
> +#include <sys/timetc.h>
>
> #include <machine/bus.h>
>
> @@ -52,18 +53,42 @@
> #define E600_WDT_WDTLR_ENABLE (1 << 1) /* Watchdog Timer
> Enable */
> #define E600_WDT_WDTLR_TIMEOUT (1 << 2) /* WDT Timeout
> Configuration */
>
> +#define E600_HPET_BASE 0xfed00000 /* HPET register base */
> +#define E600_HPET_SIZE 0x00000400 /* HPET register size */
> +
> +#define E600_HPET_GCID 0x000 /* Capabilities and ID
> */
> +#define E600_HPET_GCID_WIDTH (1 << 13) /* Counter Size */
> +#define E600_HPET_PERIOD 0x004 /* Counter Tick Period
> */
> +#define E600_HPET_GC 0x010 /* General
> Configuration */
> +#define E600_HPET_GC_ENABLE (1 << 0) /* Overall Enable */
> +#define E600_HPET_GIS 0x020 /* General Interrupt
> Status */
> +#define E600_HPET_MCV 0x0f0 /* Main Counter Value */
> +#define E600_HPET_T0C 0x100 /* Timer 0 Config and
> Capabilities */
> +#define E600_HPET_T0CV 0x108 /* Timer 0 Comparator
> Value */
> +#define E600_HPET_T1C 0x120 /* Timer 1 Config and
> Capabilities */
> +#define E600_HPET_T1CV 0x128 /* Timer 1 Comparator
> Value */
> +#define E600_HPET_T2C 0x140 /* Timer 2 Config and
> Capabilities */
> +#define E600_HPET_T2CV 0x148 /* Timer 2 Comparator
> Value */
> +
> 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)
> +#define E600_HPET_ACTIVE (1 << 1)
>
> /* Watchdog interface */
> bus_space_tag_t sc_wdt_iot;
> bus_space_handle_t sc_wdt_ioh;
>
> int sc_wdt_period;
> +
> + /* High Precision Event Timer */
> + bus_space_tag_t sc_hpet_iot;
> + bus_space_handle_t sc_hpet_ioh;
> +
> + struct timecounter sc_hpet_timecounter;
> };
>
> struct cfdriver tcpcib_cd = {
> @@ -79,6 +104,8 @@
> void tcpcib_wdt_start(struct tcpcib_softc *);
> void tcpcib_wdt_stop(struct tcpcib_softc *);
>
> +u_int tcpcib_hpet_get_timecount(struct timecounter *tc);
> +
> struct cfattach tcpcib_ca = {
> sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach,
> NULL, tcpcib_activate
> @@ -112,7 +139,6 @@
> * 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);
> @@ -129,7 +155,6 @@
> 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);
> }
> @@ -141,7 +166,6 @@
> 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);
> }
>
> @@ -160,10 +184,38 @@
> {
> struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
> struct pci_attach_args *pa = aux;
> + struct timecounter *tc = &sc->sc_hpet_timecounter;
> u_int32_t reg, wdtbase;
>
> sc->sc_active = 0;
>
> + /* High Precision Event Timer */
> + sc->sc_hpet_iot = pa->pa_memt;
> + if (bus_space_map(sc->sc_hpet_iot, E600_HPET_BASE, E600_HPET_SIZE, 0,
> + &sc->sc_hpet_ioh) == 0) {
> + tc->tc_get_timecount = tcpcib_hpet_get_timecount;
> + /* XXX 64-bit counter is not supported! */
> + tc->tc_counter_mask = 0xffffffff;
> +
> + reg = bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
> + E600_HPET_PERIOD);
> + /* femtosecs -> Hz */
> + tc->tc_frequency = 1000000000000000ULL / reg;
> +
> + tc->tc_name = sc->sc_dev.dv_xname;
> + tc->tc_quality = 1000;
> + tc->tc_priv = sc;
> + tc_init(tc);
> +
> + /* Enable counting */
> + bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
> + E600_HPET_GC, E600_HPET_GC_ENABLE);
> +
> + sc->sc_active |= E600_HPET_ACTIVE;
> +
> + printf(": %llu Hz timer", tc->tc_frequency);
> + }
> +
> /* Map Watchdog I/O space */
> reg = pci_conf_read(pa->pa_pc, pa->pa_tag, E600_LPC_WDTBA);
> wdtbase = reg & 0xffff;
> @@ -172,10 +224,11 @@
> 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");
> + printf("%c can't map watchdog I/O space",
> + sc->sc_active ? ',' : ':');
> goto corepcib;
> }
> - printf(": watchdog");
> + printf("%c watchdog", sc->sc_active ? ',' : ':');
>
> /* Check for reboot on timeout */
> reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
> @@ -235,6 +288,9 @@
> } else
> tcpcib_wdt_stop(sc);
> }
> + if (sc->sc_active & E600_HPET_ACTIVE)
> + bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
> + E600_HPET_GC, E600_HPET_GC_ENABLE);
> break;
> }
> return (0);
> @@ -266,4 +322,14 @@
> sc->sc_wdt_period = period;
>
> return (period);
> +}
> +
> +u_int
> +tcpcib_hpet_get_timecount(struct timecounter *tc)
> +{
> + struct tcpcib_softc *sc = tc->tc_priv;
> +
> + /* XXX 64-bit counter is not supported! */
> + return bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
> + E600_HPET_MCV);
> }
> --- share/man/man4/man4.i386/tcpcib.4.orig Wed May 30 12:38:14 2012
> +++ share/man/man4/man4.i386/tcpcib.4 Wed May 30 16:23:42 2012
> @@ -19,7 +19,7 @@
> .Os
> .Sh NAME
> .Nm tcpcib
> -.Nd Intel Atom E600 series LPC bridge and watchdog timer
> +.Nd Intel Atom E600 series LPC bridge, timecounter and watchdog timer
> .Sh SYNOPSIS
> .Cd "tcpcib* at pci?"
> .Cd "isa* at tcpcib?"
> @@ -27,7 +27,11 @@
> The
> .Nm
> driver provides support for the Intel Atom E600 series LPC bridge and
> -provides the standard
> +implements a 64-bit 14.3 MHz timecounter using the HPET timer.
> +.Pp
> +The
> +.Nm
> +driver also provides the standard
> .Xr watchdog 4
> interface to the watchdog timer and may be used with
> .Xr watchdogd 8 .
> @@ -60,6 +64,6 @@
> .Sh BUGS
> Apart from the core
> .Xr pcib 4
> -functionality and the
> +functionality, timecounter and the
> .Xr watchdog 4
> interface, the driver doesn't support any other aspects of the hardware.
> --- share/man/man4/man4.amd64/tcpcib.4.orig Wed May 30 12:55:24 2012
> +++ share/man/man4/man4.amd64/tcpcib.4 Wed May 30 16:23:34 2012
> @@ -19,7 +19,7 @@
> .Os
> .Sh NAME
> .Nm tcpcib
> -.Nd Intel Atom E600 series LPC bridge and watchdog timer
> +.Nd Intel Atom E600 series LPC bridge, timecounter and watchdog timer
> .Sh SYNOPSIS
> .Cd "tcpcib* at pci?"
> .Cd "isa* at tcpcib?"
> @@ -27,7 +27,11 @@
> The
> .Nm
> driver provides support for the Intel Atom E600 series LPC bridge and
> -provides the standard
> +implements a 64-bit 14.3 MHz timecounter using the HPET timer.
> +.Pp
> +The
> +.Nm
> +driver also provides the standard
> .Xr watchdog 4
> interface to the watchdog timer and may be used with
> .Xr watchdogd 8 .
> @@ -60,6 +64,6 @@
> .Sh BUGS
> Apart from the core
> .Xr pcib 4
> -functionality and the
> +functionality, timecounter and the
> .Xr watchdog 4
> interface, the driver doesn't support any other aspects of the hardware.