> Date: Mon, 4 Jun 2012 09:26:13 -0400
> From: Matt Dainty <[email protected]>
>
> * Mark Kettenis <[email protected]> [2012-06-03 08:51:03]:
> > > 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?
>
> Sure, here it is.
Thanks,
I committed this now, with one small change, increasing the quality of
the timecounter to 2000. The amdpcib(4) driver does that as well, and
it makes sense to trust real hardware a bit more than the acpi based
timecounter. Even though the HPET probably won't attach because
acpihpet(4) already stole the device.
Thanks again,
Mark
> --- sys/dev/pci/tcpcib.c.orig Thu May 31 14:17:23 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
> @@ -157,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;
> @@ -169,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,
> @@ -232,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);
> @@ -263,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.