diff options
-rw-r--r-- | sys/arch/i386/pci/elan520.c | 65 | ||||
-rw-r--r-- | sys/arch/i386/pci/elan520reg.h | 23 |
2 files changed, 81 insertions, 7 deletions
diff --git a/sys/arch/i386/pci/elan520.c b/sys/arch/i386/pci/elan520.c index a97345b3ab5..e380c841af6 100644 --- a/sys/arch/i386/pci/elan520.c +++ b/sys/arch/i386/pci/elan520.c @@ -1,4 +1,4 @@ -/* $OpenBSD: elan520.c,v 1.12 2006/12/12 23:14:27 dim Exp $ */ +/* $OpenBSD: elan520.c,v 1.13 2007/05/23 11:55:11 markus Exp $ */ /* $NetBSD: elan520.c,v 1.4 2002/10/02 05:47:15 thorpej Exp $ */ /*- @@ -48,6 +48,8 @@ #include <sys/device.h> #include <sys/gpio.h> #include <sys/sysctl.h> +#include <sys/time.h> +#include <sys/timetc.h> #include <machine/bus.h> @@ -66,6 +68,9 @@ struct elansc_softc { /* GPIO interface */ struct gpio_chipset_tag sc_gpio_gc; gpio_pin_t sc_gpio_pins[ELANSC_PIO_NPINS]; + + /* GP timer */ + struct timecounter sc_tc; } *elansc; int elansc_match(struct device *, void *, void *); @@ -83,6 +88,8 @@ int elansc_gpio_pin_read(void *, int); void elansc_gpio_pin_write(void *, int, int); void elansc_gpio_pin_ctl(void *, int, int); +u_int elansc_tc_read(struct timecounter *); + struct cfattach elansc_ca = { sizeof(struct elansc_softc), elansc_match, elansc_attach }; @@ -120,11 +127,10 @@ elansc_attach(struct device *parent, struct device *self, void *aux) struct elansc_softc *sc = (void *) self; struct pci_attach_args *pa = aux; struct gpiobus_attach_args gba; - uint16_t rev; - uint8_t ressta, cpuctl; - int pin; - int reg, shift; - u_int16_t data; + struct timecounter *tc; + uint16_t rev, data; + uint8_t ressta, cpuctl, tmr; + int pin, reg, shift; sc->sc_memt = pa->pa_memt; if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, NBPG, 0, @@ -198,6 +204,53 @@ elansc_attach(struct device *parent, struct device *self, void *aux) /* Attach GPIO framework */ config_found(&sc->sc_dev, &gba, gpiobus_print); + + /* Disable GP1/2, clear the current count, and set the period to max */ + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL, + GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP | + GPTMRCTL_PSC_SEL | GPTMRCTL_RTG); + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CNT, 0); + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1MAXCMPA, 0); + + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL, + GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP); + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CNT, 0); + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2MAXCMPA, 0); + + tmr = bus_space_read_1(sc->sc_memt, sc->sc_memh, SWTMRCFG); + + /* Enable GP1/2 */ + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR1CTL, + GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP | + GPTMRCTL_PSC_SEL | GPTMRCTL_RTG); + bus_space_write_2(sc->sc_memt, sc->sc_memh, GPTMR2CTL, + GPTMRCTL_ENB | GPTMRCTL_ENB_WR | GPTMRCTL_CONT_CMP); + + /* Attach timer */ + tc = &sc->sc_tc; + tc->tc_get_timecount = elansc_tc_read; + tc->tc_poll_pps = NULL; + tc->tc_counter_mask = ~0; + tc->tc_frequency = (tmr & 1) ? (33000000 / 4) : (33333333 / 4); + tc->tc_name = sc->sc_dev.dv_xname; + tc->tc_quality = 1000; + tc->tc_priv = sc; + tc_init(tc); +} + +u_int +elansc_tc_read(struct timecounter *tc) +{ + struct elansc_softc *sc = tc->tc_priv; + u_int32_t m1, m2, l; + + do { + m1 = bus_space_read_2(sc->sc_memt, sc->sc_memh, GPTMR1CNT); + l = bus_space_read_2(sc->sc_memt, sc->sc_memh, GPTMR2CNT); + m2 = bus_space_read_2(sc->sc_memt, sc->sc_memh, GPTMR1CNT); + } while (m1 != m2); + + return ((m1 << 16) | l); } void diff --git a/sys/arch/i386/pci/elan520reg.h b/sys/arch/i386/pci/elan520reg.h index 2f954bdcaea..60d00d556f2 100644 --- a/sys/arch/i386/pci/elan520reg.h +++ b/sys/arch/i386/pci/elan520reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: elan520reg.h,v 1.2 2004/06/05 15:06:22 grange Exp $ */ +/* $OpenBSD: elan520reg.h,v 1.3 2007/05/23 11:55:11 markus Exp $ */ /* $NetBSD: elan520reg.h,v 1.1 2002/08/12 01:03:14 thorpej Exp $ */ /*- @@ -146,4 +146,25 @@ #define RESSTA_ICE_HRST_DET 0x20 /* AMDebug(tm) soft reset detect */ #define RESSTA_SCP_RST 0x40 /* SCP reset detect */ +/* + * General-Purpose Timers + */ +#define SWTMRCFG 0xc64 /* Software Timer Configuration */ +#define GPTMR0CTL 0xc72 /* GP Timer 0 mode/control */ +#define GPTMR0CNT 0xc74 /* GP Timer 0 current count value */ +#define GPTMR0MAXCMPA 0xc76 /* GP Timer 0 maxcount value A */ +#define GPTMR0MAXCMPB 0xc78 /* GP Timer 0 maxcount value B */ +#define GPTMR1CTL 0xc7a /* GP Timer 1 mode/control */ +#define GPTMR1CNT 0xc7c /* GP Timer 1 current count value */ +#define GPTMR1MAXCMPA 0xc7e /* GP Timer 1 maxcount value A */ +#define GPTMR1MAXCMPB 0xc80 /* GP Timer 1 maxcount value B */ +#define GPTMR2CTL 0xc82 /* GP Timer 2 mode/control */ +#define GPTMR2CNT 0xc84 /* GP Timer 2 current count value */ +#define GPTMR2MAXCMPA 0xc8e /* GP Timer 2 maxcount value A */ +#define GPTMRCTL_CONT_CMP 0x0001 /* GP Timer continuous mode */ +#define GPTMRCTL_RTG 0x0010 /* GP Timer retrigger */ +#define GPTMRCTL_PSC_SEL 0x0008 /* GP Timer prescaler */ +#define GPTMRCTL_ENB 0x8000 /* GP Timer enable */ +#define GPTMRCTL_ENB_WR 0x4000 /* GP Timer enable bit write */ + #endif /* _I386_PCI_ELAN520REG_H_ */ |