diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2013-04-26 00:09:15 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2013-04-26 00:09:15 +0000 |
commit | 26f71142a96260c0e7cd61ac9b21578ec31acbc2 (patch) | |
tree | 17ba8a1bbb94934105534f23251b86af5dd09bb9 | |
parent | 4db4ddb705b3568cb8b4d70911d4bf3f96dcca3c (diff) |
Clean up ARM's generic interrupt controller and timer. Add the ability to
change the frequency and add match functions.
ok bmercer@
-rw-r--r-- | sys/arch/beagle/dev/ampintc.c | 21 | ||||
-rw-r--r-- | sys/arch/beagle/dev/amptimer.c | 71 |
2 files changed, 62 insertions, 30 deletions
diff --git a/sys/arch/beagle/dev/ampintc.c b/sys/arch/beagle/dev/ampintc.c index 04ef4cc3403..0a37fcdb868 100644 --- a/sys/arch/beagle/dev/ampintc.c +++ b/sys/arch/beagle/dev/ampintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ampintc.c,v 1.10 2013/04/25 22:14:17 patrick Exp $ */ +/* $OpenBSD: ampintc.c,v 1.11 2013/04/26 00:09:14 patrick Exp $ */ /* * Copyright (c) 2007,2009,2011 Dale Rahn <drahn@openbsd.org> * @@ -153,6 +153,7 @@ struct intrq { }; +int ampintc_match(struct device *, void *, void *); void ampintc_attach(struct device *, struct device *, void *); int ampintc_spllower(int); void ampintc_splx(int); @@ -174,13 +175,19 @@ void ampintc_intr_disable(int); void ampintc_route(int, int , int); struct cfattach ampintc_ca = { - sizeof (struct ampintc_softc), NULL, ampintc_attach + sizeof (struct ampintc_softc), ampintc_match, ampintc_attach }; struct cfdriver ampintc_cd = { NULL, "ampintc", DV_DULL }; +int +ampintc_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + void ampintc_attach(struct device *parent, struct device *self, void *args) { @@ -260,7 +267,7 @@ ampintc_attach(struct device *parent, struct device *self, void *args) void ampintc_set_priority(int irq, int pri) { - struct ampintc_softc *sc = ampintc; + struct ampintc_softc *sc = ampintc; uint32_t prival; /* @@ -293,7 +300,7 @@ ampintc_setipl(int new) void ampintc_intr_enable(int irq) { - struct ampintc_softc *sc = ampintc; + struct ampintc_softc *sc = ampintc; #ifdef DEBUG printf("enable irq %d register %x bitmask %08x\n", @@ -307,7 +314,7 @@ ampintc_intr_enable(int irq) void ampintc_intr_disable(int irq) { - struct ampintc_softc *sc = ampintc; + struct ampintc_softc *sc = ampintc; bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICERn(irq), 1 << IRQ_TO_REG32BIT(irq)); @@ -369,7 +376,7 @@ ampintc_splx(int new) { struct cpu_info *ci = curcpu(); - if (ci->ci_ipending & arm_smask[new]) + if (ci->ci_ipending & arm_smask[new]) arm_do_pending_intr(new); ampintc_setipl(new); @@ -402,7 +409,7 @@ ampintc_splraise(int new) new = old; ampintc_setipl(new); - + return (old); } diff --git a/sys/arch/beagle/dev/amptimer.c b/sys/arch/beagle/dev/amptimer.c index 4ce4005e6e0..c09bed24de6 100644 --- a/sys/arch/beagle/dev/amptimer.c +++ b/sys/arch/beagle/dev/amptimer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: amptimer.c,v 1.7 2011/11/16 14:06:32 drahn Exp $ */ +/* $OpenBSD: amptimer.c,v 1.8 2013/04/26 00:09:14 patrick Exp $ */ /* * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org> * @@ -29,32 +29,33 @@ #include <machine/intr.h> #include <beagle/dev/omapvar.h> +/* registers */ #define GTIMER_CNT_LOW 0x200 #define GTIMER_CNT_HIGH 0x204 #define GTIMER_CTRL 0x208 -#define GTIMER_CTRL_AA (1 << 3) -#define GTIMER_CTRL_IRQ (1 << 2) -#define GTIMER_CTRL_COMP (1 << 1) -#define GTIMER_CTRL_TIMER (1 << 0) +#define GTIMER_CTRL_AA (1 << 3) +#define GTIMER_CTRL_IRQ (1 << 2) +#define GTIMER_CTRL_COMP (1 << 1) +#define GTIMER_CTRL_TIMER (1 << 0) #define GTIMER_STATUS 0x20c -#define GTIMER_STATUS_EVENT (1 << 0) +#define GTIMER_STATUS_EVENT (1 << 0) #define GTIMER_CMP_LOW 0x210 #define GTIMER_CMP_HIGH 0x214 #define GTIMER_AUTOINC 0x218 -/* XXX - PERIPHCLK */ -#define TIMER_FREQUENCY 500 * 1000 * 1000 /* XXX - PERIPHCLK? */ +#define TIMER_FREQUENCY 500 * 1000 * 1000 /* ARM core clock */ +int32_t amptimer_frequency = TIMER_FREQUENCY; u_int amptimer_get_timecount(struct timecounter *); static struct timecounter amptimer_timecounter = { - amptimer_get_timecount, NULL, 0x7fffffff, 0, "amptimer", 0, NULL + amptimer_get_timecount, NULL, 0x7fffffff, 0, "amptimer", 0, NULL }; struct amptimer_softc { struct device sc_dev; - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; volatile u_int64_t sc_nexttickevent; volatile u_int64_t sc_nextstatevent; u_int32_t sc_ticks_per_second; @@ -70,12 +71,14 @@ struct amptimer_softc { #endif }; +int amptimer_match(struct device *, void *, void *); void amptimer_attach(struct device *, struct device *, void *); uint64_t amptimer_readcnt64(struct amptimer_softc *sc); int amptimer_intr(void *); void amptimer_cpu_initclocks(void); void amptimer_delay(u_int); void amptimer_setstatclockrate(int stathz); +void amptimer_set_clockrate(int32_t new_frequency); /* hack - XXXX * gptimer connects directly to ampintc, not thru the generic @@ -87,7 +90,7 @@ void *ampintc_intr_establish(int, int, int (*)(void *), void *, char *); struct cfattach amptimer_ca = { - sizeof (struct amptimer_softc), NULL, amptimer_attach + sizeof (struct amptimer_softc), amptimer_match, amptimer_attach }; struct cfdriver amptimer_cd = { @@ -98,8 +101,8 @@ uint64_t amptimer_readcnt64(struct amptimer_softc *sc) { uint32_t high0, high1, low; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; do { high0 = bus_space_read_4(iot, ioh, GTIMER_CNT_HIGH); @@ -110,6 +113,11 @@ amptimer_readcnt64(struct amptimer_softc *sc) return ((((uint64_t)high1) << 32) | low); } +int +amptimer_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} void amptimer_attach(struct device *parent, struct device *self, void *args) @@ -124,8 +132,8 @@ amptimer_attach(struct device *parent, struct device *self, void *args) oa->oa_dev->mem[0].size, 0, &ioh)) panic("amptimer_attach: bus_space_map failed!"); - sc->sc_ticks_per_second = TIMER_FREQUENCY; - printf(": tick rate %d KHz\n", sc->sc_ticks_per_second /1024); + sc->sc_ticks_per_second = amptimer_frequency; + printf(": tick rate %d KHz\n", sc->sc_ticks_per_second /1000); sc->sc_ioh = ioh; @@ -165,7 +173,7 @@ u_int amptimer_get_timecount(struct timecounter *tc) { struct amptimer_softc *sc = amptimer_timecounter.tc_priv; - return bus_space_read_4(sc->sc_iot, sc->sc_ioh, GTIMER_CNT_LOW); + return bus_space_read_4(sc->sc_iot, sc->sc_ioh, GTIMER_CNT_LOW); } @@ -238,7 +246,7 @@ again: nextevent >> 32); reg |= GTIMER_CTRL_COMP; bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTIMER_CTRL, reg); - + now = amptimer_readcnt64(sc); if (now >= nextevent) { nextevent = now + skip; @@ -250,6 +258,22 @@ again: } void +amptimer_set_clockrate(int32_t new_frequency) +{ + struct amptimer_softc *sc = amptimer_cd.cd_devs[0]; + + amptimer_frequency = new_frequency; + + if (sc == NULL) + return; + + sc->sc_ticks_per_second = amptimer_frequency; + amptimer_timecounter.tc_frequency = sc->sc_ticks_per_second; + printf("amptimer0: adjusting clock: new tick rate %d KHz\n", + sc->sc_ticks_per_second /1000); +} + +void amptimer_cpu_initclocks() { struct amptimer_softc *sc = amptimer_cd.cd_devs[0]; @@ -259,7 +283,9 @@ amptimer_cpu_initclocks() stathz = hz; profhz = hz * 10; - sc->sc_ticks_per_second = TIMER_FREQUENCY; + if (sc->sc_ticks_per_second != amptimer_frequency) { + amptimer_set_clockrate(amptimer_frequency); + } amptimer_setstatclockrate(stathz); @@ -285,8 +311,8 @@ amptimer_cpu_initclocks() next >> 32); reg |= GTIMER_CTRL_COMP | GTIMER_CTRL_IRQ; bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTIMER_CTRL, reg); - } + void amptimer_delay(u_int usecs) { @@ -318,7 +344,6 @@ amptimer_delay(u_int usecs) if (delta > delaycnt) break; } - } void @@ -327,7 +352,7 @@ amptimer_setstatclockrate(int newhz) struct amptimer_softc *sc = amptimer_cd.cd_devs[0]; int minint, statint; int s; - + s = splclock(); statint = sc->sc_ticks_per_second / newhz; @@ -338,7 +363,7 @@ amptimer_setstatclockrate(int newhz) sc->sc_statvar >>= 1; sc->sc_statmin = statint - (sc->sc_statvar >> 1); - + splx(s); /* |