Dynamically attach agtimer(4). Since agtimer(4) also provides the delay()
authorkettenis <kettenis@openbsd.org>
Wed, 10 Aug 2016 06:51:57 +0000 (06:51 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 10 Aug 2016 06:51:57 +0000 (06:51 +0000)
function for platforms that have it, rework the code a bit such that it can
be used before agtimer(4) attaches.  Introduce a new agtimer_init()
function that checks whether the CPU implements the Generic Timer feature
and switches to agtimer_delay() if that feature is present.  Call this
function from the generic platform initialization code.

ok jsg@

sys/arch/arm/cortex/agtimer.c
sys/arch/arm/cortex/files.cortex
sys/arch/armv7/armv7/platform.c
sys/arch/armv7/conf/GENERIC

index 38c8eda..c2692c1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: agtimer.c,v 1.6 2016/08/05 13:31:29 kettenis Exp $ */
+/* $OpenBSD: agtimer.c,v 1.7 2016/08/10 06:51:57 kettenis Exp $ */
 /*
  * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
 #include <sys/timetc.h>
 #include <sys/evcount.h>
 
-#include <arm/cpufunc.h>
-#include <machine/bus.h>
 #include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/cpufunc.h>
 #include <arm/cortex/cortex.h>
 
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+
 /* registers */
 #define GTIMER_CNTP_CTL_ENABLE         (1 << 0)
 #define GTIMER_CNTP_CTL_IMASK          (1 << 1)
@@ -54,6 +59,7 @@ struct agtimer_pcpu_softc {
 
 struct agtimer_softc {
        struct device           sc_dev;
+       int                     sc_node;
 
        struct agtimer_pcpu_softc sc_pstat[MAX_ARM_CPUS];
 
@@ -71,7 +77,7 @@ struct agtimer_softc {
 
 int            agtimer_match(struct device *, void *, void *);
 void           agtimer_attach(struct device *, struct device *, void *);
-uint64_t       agtimer_readcnt64(struct agtimer_softc *sc);
+uint64_t       agtimer_readcnt64(void);
 int            agtimer_intr(void *);
 void           agtimer_cpu_initclocks(void);
 void           agtimer_delay(u_int);
@@ -79,15 +85,6 @@ void         agtimer_setstatclockrate(int stathz);
 void           agtimer_set_clockrate(int32_t new_frequency);
 void           agtimer_startclock(void);
 
-/* hack - XXXX
- * agtimer connects directly to ampintc, not thru the generic
- * interface because it uses an 'internal' interrupt
- * not a peripheral interrupt.
- */
-void   *ampintc_intr_establish(int, int, int (*)(void *), void *, char *);
-
-
-
 struct cfattach agtimer_ca = {
        sizeof (struct agtimer_softc), agtimer_match, agtimer_attach
 };
@@ -97,7 +94,7 @@ struct cfdriver agtimer_cd = {
 };
 
 uint64_t
-agtimer_readcnt64(struct agtimer_softc *sc)
+agtimer_readcnt64(void)
 {
        uint64_t val;
 
@@ -152,20 +149,23 @@ agtimer_set_tval(uint32_t val)
 int
 agtimer_match(struct device *parent, void *cfdata, void *aux)
 {
-       if ((cpufunc_id() & CPU_ID_CORTEX_A7_MASK) == CPU_ID_CORTEX_A7 ||
-           (cpufunc_id() & CPU_ID_CORTEX_A15_MASK) == CPU_ID_CORTEX_A15 ||
-           (cpufunc_id() & CPU_ID_CORTEX_A17_MASK) == CPU_ID_CORTEX_A17)
-               return (1);
+       struct fdt_attach_args *faa = (struct fdt_attach_args *)aux;
 
-       return 0;
+       return OF_is_compatible(faa->fa_node, "arm,armv7-timer");
 }
 
 void
-agtimer_attach(struct device *parent, struct device *self, void *args)
+agtimer_attach(struct device *parent, struct device *self, void *aux)
 {
        struct agtimer_softc *sc = (struct agtimer_softc *)self;
+       struct fdt_attach_args *faa = aux;
+
+       sc->sc_node = faa->fa_node;
 
+       agtimer_frequency =
+           OF_getpropint(sc->sc_node, "clock-frequency", agtimer_frequency);
        sc->sc_ticks_per_second = agtimer_frequency;
+
        printf(": tick rate %d KHz\n", sc->sc_ticks_per_second /1000);
 
        /* XXX: disable user access */
@@ -192,8 +192,7 @@ agtimer_attach(struct device *parent, struct device *self, void *args)
 u_int
 agtimer_get_timecount(struct timecounter *tc)
 {
-       struct agtimer_softc *sc = agtimer_timecounter.tc_priv;
-       return agtimer_readcnt64(sc);
+       return agtimer_readcnt64();
 }
 
 int
@@ -218,7 +217,7 @@ agtimer_intr(void *frame)
         * do the right thing
         */
 
-       now = agtimer_readcnt64(sc);
+       now = agtimer_readcnt64();
 
        while (pc->pc_nexttickevent <= now) {
                pc->pc_nexttickevent += sc->sc_ticks_per_intr;
@@ -301,17 +300,13 @@ agtimer_cpu_initclocks()
        sc->sc_ticks_err_cnt = sc->sc_ticks_per_second % hz;
        pc->pc_ticks_err_sum = 0;
 
-       /* establish interrupts */
-       /* XXX - irq */
-
-       /* secure physical timer */
-       ampintc_intr_establish(29, IPL_CLOCK, agtimer_intr,
-           NULL, "tick");
-       /* non-secure physical timer */
-       ampintc_intr_establish(30, IPL_CLOCK, agtimer_intr,
-           NULL, "tick");
+       /* Setup secure and non-secure timer IRQs. */
+       arm_intr_establish_fdt_idx(sc->sc_node, 0, IPL_CLOCK,
+           agtimer_intr, NULL, "tick");
+       arm_intr_establish_fdt_idx(sc->sc_node, 1, IPL_CLOCK,
+           agtimer_intr, NULL, "tick");
 
-       next = agtimer_readcnt64(sc) + sc->sc_ticks_per_intr;
+       next = agtimer_readcnt64() + sc->sc_ticks_per_intr;
        pc->pc_nexttickevent = pc->pc_nextstatevent = next;
 
        reg = agtimer_get_ctrl();
@@ -324,29 +319,28 @@ agtimer_cpu_initclocks()
 void
 agtimer_delay(u_int usecs)
 {
-       struct agtimer_softc    *sc = agtimer_cd.cd_devs[0];
        u_int32_t               clock, oclock, delta, delaycnt;
        volatile int            j;
        int                     csec, usec;
 
-       if (usecs > (0x80000000 / (sc->sc_ticks_per_second))) {
+       if (usecs > (0x80000000 / agtimer_frequency)) {
                csec = usecs / 10000;
                usec = usecs % 10000;
 
-               delaycnt = (sc->sc_ticks_per_second / 100) * csec +
-                   (sc->sc_ticks_per_second / 100) * usec / 10000;
+               delaycnt = (agtimer_frequency / 100) * csec +
+                   (agtimer_frequency / 100) * usec / 10000;
        } else {
-               delaycnt = sc->sc_ticks_per_second * usecs / 1000000;
+               delaycnt = agtimer_frequency * usecs / 1000000;
        }
        if (delaycnt <= 1)
                for (j = 100; j > 0; j--)
                        ;
 
-       oclock = agtimer_readcnt64(sc);
+       oclock = agtimer_readcnt64();
        while (1) {
                for (j = 100; j > 0; j--)
                        ;
-               clock = agtimer_readcnt64(sc);
+               clock = agtimer_readcnt64();
                delta = clock - oclock;
                if (delta > delaycnt)
                        break;
@@ -387,7 +381,7 @@ agtimer_startclock(void)
        uint64_t nextevent;
        uint32_t reg;
 
-       nextevent = agtimer_readcnt64(sc) + sc->sc_ticks_per_intr;
+       nextevent = agtimer_readcnt64() + sc->sc_ticks_per_intr;
        pc->pc_nexttickevent = pc->pc_nextstatevent = nextevent;
 
        reg = agtimer_get_ctrl();
@@ -396,3 +390,19 @@ agtimer_startclock(void)
        agtimer_set_tval(sc->sc_ticks_per_second);
        agtimer_set_ctrl(reg);
 }
+
+void
+agtimer_init(void)
+{
+       uint32_t id_pfr1, cntfrq = 0;
+
+       /* Check for Generic Timer support. */
+       __asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
+       if ((id_pfr1 & 0x000f0000) == 0x00010000)
+               __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (cntfrq));
+
+       if (cntfrq != 0) {
+               agtimer_frequency = cntfrq;
+               arm_clock_register(NULL, agtimer_delay, NULL, NULL);
+       }
+}
index 630dabb..72b0256 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.cortex,v 1.5 2016/08/04 15:52:52 kettenis Exp $
+#      $OpenBSD: files.cortex,v 1.6 2016/08/10 06:51:57 kettenis Exp $
 
 # ARM core
 device cortex {}
@@ -14,7 +14,7 @@ attach        amptimer at cortex
 file   arch/arm/cortex/amptimer.c              amptimer
 
 device agtimer
-attach agtimer at cortex
+attach agtimer at fdt
 file   arch/arm/cortex/agtimer.c               agtimer
 
 device armliicc
index b0eb469..aa2bafa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: platform.c,v 1.9 2016/08/07 17:46:36 kettenis Exp $   */
+/*     $OpenBSD: platform.c,v 1.10 2016/08/10 06:51:57 kettenis Exp $  */
 /*
  * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
  *
@@ -34,6 +34,8 @@
 
 static struct armv7_platform *platform;
 
+void   agtimer_init(void);
+
 void   exuart_init_cons(void);
 void   imxuart_init_cons(void);
 void   omapuart_init_cons(void);
@@ -73,7 +75,9 @@ void
 platform_init(void)
 {
        int i;
-       
+
+       agtimer_init();
+
        for (i = 0; i < nitems(plat_match); i++) {
                platform = plat_match[i]();
                if (platform != NULL)
index f3805be..f9fdf06 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.42 2016/08/07 17:46:36 kettenis Exp $
+#      $OpenBSD: GENERIC,v 1.43 2016/08/10 06:51:57 kettenis Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -35,7 +35,7 @@ cpu0          at mainbus?
 cortex0                at mainbus?
 ampintc*       at fdt?
 amptimer*      at cortex?
-agtimer*       at cortex?
+agtimer*       at fdt?
 armliicc*      at cortex?
 
 # iMX