On Tue, Feb 02, 2016 at 10:55:57AM +1100, Jonathan Gray wrote:
> 
> Thanks, both diffs committed.  Any chance you could create another to
> move the sxitimer_* globals into the softc?

I left out moving of sxitimer_iot and sxitimer_ioh on purpose, as
it would make reviewing this alot worse.
Now if this does get in somewhat as is, i wouldn't have much problems
producing diff to fix/unify armv7 timers allowing to remove some duplicate
code etc. with main reason being that afterwards all of them would be usable
with "-D_STANDALONE", being one of the ingredients to arch/armv7/stand :)
incase it does happen to be on your roadmap.

See the diff simplifying code and correcting comments in sxitimer below.

-Artturi


diff --git a/sys/arch/armv7/sunxi/sun4i.c b/sys/arch/armv7/sunxi/sun4i.c
index 6c3197a..1269b8c 100644
--- a/sys/arch/armv7/sunxi/sun4i.c
+++ b/sys/arch/armv7/sunxi/sun4i.c
@@ -44,17 +44,10 @@ struct armv7_dev sxia1x_devs[] = {
          .mem = { { INTC_ADDR, INTC_SIZE } },
        },
 
-       /* Timers/Counters, resources mapped on first unit */
+       /* Timer/Counter */
        { .name = "sxitimer",
          .unit = 0,
-         .mem = {      { TIMER_ADDR, TIMERx_SIZE },
-                       { CPUCNTRS_ADDR, CPUCNTRS_ADDR } }
-       },
-       { .name = "sxitimer",
-         .unit = 1,
-       },
-       { .name = "sxitimer",
-         .unit = 2,
+         .mem = { { TIMER_ADDR, TIMERx_SIZE } }
        },
 
        /* Watchdog Timer */
diff --git a/sys/arch/armv7/sunxi/sunxi.c b/sys/arch/armv7/sunxi/sunxi.c
index dac0348..a8efab96 100644
--- a/sys/arch/armv7/sunxi/sunxi.c
+++ b/sys/arch/armv7/sunxi/sunxi.c
@@ -41,8 +41,6 @@ struct board_dev sun4i_devs[] = {
        { "sxiccmu",    0 },
        { "a1xintc",    0 },
        { "sxitimer",   0 },
-       { "sxitimer",   1 },
-       { "sxitimer",   2 },
        { "sxidog",     0 },
        { "sxirtc",     0 },
        { "sxiuart",    0 },
diff --git a/sys/arch/armv7/sunxi/sunxireg.h b/sys/arch/armv7/sunxi/sunxireg.h
index 8153efa..9151669 100644
--- a/sys/arch/armv7/sunxi/sunxireg.h
+++ b/sys/arch/armv7/sunxi/sunxireg.h
@@ -60,10 +60,7 @@
 
 #define        TIMER_ADDR              0x01c20c00
 #define        TIMERx_SIZE             0x200
-#define        TIMER0_IRQ              22
-#define        TIMER1_IRQ              23
-#define        TIMER2_IRQ              24
-#define        STATTIMER_IRQ           TIMER1_IRQ /* XXX */
+#define        TIMER_IRQNUM(x)         (22 + (x))
 
 #define        WDOG_ADDR               0x01c20c90
 #define        WDOG_SIZE               0x08
diff --git a/sys/arch/armv7/sunxi/sxitimer.c b/sys/arch/armv7/sunxi/sxitimer.c
index 4062b87..a5d5dd0 100644
--- a/sys/arch/armv7/sunxi/sxitimer.c
+++ b/sys/arch/armv7/sunxi/sxitimer.c
@@ -34,7 +34,6 @@
 
 #include <armv7/armv7/armv7var.h>
 #include <armv7/sunxi/sunxireg.h>
-/* #include <armv7/sunxi/sxipiovar.h> */
 
 #define        TIMER_IER               0x00
 #define        TIMER_ISR               0x04
@@ -75,6 +74,13 @@
 #define        TICKTIMER               0
 #define        STATTIMER               1
 #define        CNTRTIMER               2
+#define        TICKFREQ                TIMER0_FREQUENCY
+#define        STATFREQ                TIMER1_FREQUENCY
+#define        CNTRFREQ                TIMER2_FREQUENCY
+/* timers are down-counters, from interval to 0 */
+#define        MAX_IVAL                0xffffffff      /* max interval */
+
+#define        TIMER_MIN_CYCLES        0x20    /* 'feel good' value */
 
 void   sxitimer_attach(struct device *, struct device *, void *);
 int    sxitimer_tickintr(void *);
@@ -94,27 +100,13 @@ static struct timecounter sxitimer_timecounter = {
 bus_space_tag_t                sxitimer_iot;
 bus_space_handle_t     sxitimer_ioh;
 
-uint32_t sxitimer_freq[] = {
-       TIMER0_FREQUENCY,
-       TIMER1_FREQUENCY,
-       TIMER2_FREQUENCY,
-       0
-};
-
-uint32_t sxitimer_irq[] = {
-       TIMER0_IRQ,
-       TIMER1_IRQ,
-       TIMER2_IRQ,
-       0
-};
-
-uint32_t sxitimer_stat_tpi, sxitimer_tick_tpi;
-uint32_t sxitimer_statvar, sxitimer_statmin;
-uint32_t sxitimer_tick_nextevt, sxitimer_stat_nextevt;
-uint32_t sxitimer_ticks_err_cnt, sxitimer_ticks_err_sum;
-
 struct sxitimer_softc {
        struct device           sc_dev;
+       uint32_t                statvar, statmin;
+       uint32_t                stat_tpi, stat_nextevt;
+       uint32_t                tick_tpi, tick_nextevt;
+       uint32_t                ticks_err_cnt, ticks_err_sum;
+
 };
 
 struct cfattach        sxitimer_ca = {
@@ -128,12 +120,11 @@ struct cfdriver sxitimer_cd = {
 void
 sxitimer_attach(struct device *parent, struct device *self, void *args)
 {
+       struct sxitimer_softc *sc = (struct sxitimer_softc *)self;
        struct armv7_attach_args *aa = args;
-       uint32_t freq, ival, now, cr;
-       int unit = self->dv_unit;
-
-       if (unit != 0)
-               goto skip_init;
+       
+       if (self->dv_unit != 0)
+               panic("sxitimer_attach: unit = %d", self->dv_unit);
 
        sxitimer_iot = aa->aa_iot;
 
@@ -143,83 +134,66 @@ sxitimer_attach(struct device *parent, struct device 
*self, void *args)
 
        /* clear counter, loop until ready */
        bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL,
-           CNT64_CLR_EN); /* XXX as a side-effect counter clk src=OSC24M */
+           CNT64_CLR_EN);      /* as a side-effect counter clk src=OSC24M */
        while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL)
            & CNT64_CLR_EN)
                continue;
 
        /* setup timers */
-       cr = bus_space_read_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL);
-       cr |= OSC32K_SRC_SEL; /* ext 32.768KHz OSC src */
-       bus_space_write_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL, cr);
-
-skip_init:
-       /* timers are down-counters, from interval to 0 */
-       now = 0xffffffff; /* known big value */
-       freq = sxitimer_freq[unit];
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL,
+           bus_space_read_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL) |
+           OSC32K_SRC_SEL); /* ext 32.768KHz OSC src */
 
        /* stop timer, and set clk src */
-       bus_space_write_4(sxitimer_iot, sxitimer_ioh,
-           TIMER_CTRL(unit),
-           freq == 24000000 ? TIMER_OSC24M : TIMER_LSOSC);
-
-       switch (unit) { /* XXX more XXXXTIMER magic for less lines? */
-       case TICKTIMER:
-               ival = sxitimer_tick_tpi = freq / hz;
-               sxitimer_tick_nextevt = now - ival;
-
-               sxitimer_ticks_err_cnt = freq % hz;
-               sxitimer_ticks_err_sum = 0;
-
-               printf(": ticktimer %dhz @ %dKHz", hz, freq / 1000);
-               break;
-       case STATTIMER:
-               /* 100/1000 or 128/1024 ? */
-               stathz = 128;
-               profhz = 1024;
-               sxitimer_setstatclockrate(stathz);
-
-               ival = sxitimer_stat_tpi = freq / stathz;
-               sxitimer_stat_nextevt = now - ival;
-
-               printf(": stattimer %dhz @ %dKHz", stathz, freq / 1000);
-               break;
-       case CNTRTIMER:
-               ival = now;
-
-               sxitimer_timecounter.tc_frequency = freq;
-               tc_init(&sxitimer_timecounter);
-               arm_clock_register(sxitimer_cpu_initclocks, sxitimer_delay,
-                   sxitimer_setstatclockrate, NULL);
-
-               printf(": cntrtimer @ %dKHz", freq / 1000);
-               break;
-       default:
-               panic("sxitimer_attach: unit = %d", unit);
-               break;
-       }
-
-       bus_space_write_4(sxitimer_iot, sxitimer_ioh,
-           TIMER_INTV(unit), ival);
-
-       printf("\n");
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_CTRL(TICKTIMER),
+           TICKFREQ == 24000000 ? TIMER_OSC24M : TIMER_LSOSC);
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_CTRL(STATTIMER),
+           STATFREQ == 24000000 ? TIMER_OSC24M : TIMER_LSOSC);
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_CTRL(CNTRTIMER),
+           CNTRFREQ == 24000000 ? TIMER_OSC24M : TIMER_LSOSC);
+
+       /* prepare tick */
+       sc->tick_tpi = TICKFREQ / hz;
+       sc->tick_nextevt = MAX_IVAL - sc->tick_tpi;
+
+       sc->ticks_err_cnt = TICKFREQ % hz;
+       sc->ticks_err_sum = 0;
+
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_INTV(TICKTIMER),
+           sc->tick_tpi);
+       printf(": tick %dhz @ %dKHz", hz, TICKFREQ / 1000);
+
+       /* prepare stat */
+       stathz = 128;   /* 100/1000 or 128/1024 ? */
+       profhz = 1024;
+       sxitimer_setstatclockrate(stathz);
+
+       sc->stat_tpi = STATFREQ / stathz;
+       sc->stat_nextevt = MAX_IVAL - sc->stat_tpi;
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_INTV(STATTIMER),
+           sc->stat_tpi);
+       printf(" stat %dhz @ %dKHz", stathz, STATFREQ / 1000);
+
+       /* prepare counter */
+       sxitimer_timecounter.tc_frequency = CNTRFREQ;
+       tc_init(&sxitimer_timecounter);
+       arm_clock_register(sxitimer_cpu_initclocks, sxitimer_delay,
+           sxitimer_setstatclockrate, NULL);
+
+       bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_INTV(CNTRTIMER),
+           MAX_IVAL);
+       printf(" counter @ %dKHz\n", CNTRFREQ / 1000);
 }
 
-/*
- * would be interesting to play with trigger mode while having one timer
- * in 32KHz mode, and the other timer running in sysclk mode and use
- * the high resolution speeds (matters more for delay than tick timer)
- */
-
 void
 sxitimer_cpu_initclocks(void)
 {
        uint32_t isr, ier;
 
        /* establish interrupts */
-       arm_intr_establish(sxitimer_irq[TICKTIMER], IPL_CLOCK,
+       arm_intr_establish(TIMER_IRQNUM(TICKTIMER), IPL_CLOCK,
            sxitimer_tickintr, NULL, "tick");
-       arm_intr_establish(sxitimer_irq[STATTIMER], IPL_STATCLOCK,
+       arm_intr_establish(TIMER_IRQNUM(STATTIMER), IPL_STATCLOCK,
            sxitimer_statintr, NULL, "stattick");
 
        /* clear timer interrupt pending bits */
@@ -247,25 +221,22 @@ sxitimer_cpu_initclocks(void)
 }
 
 /* 
- * See comment in arm/xscale/i80321_clock.c
- *
- * Counter is count up, but with autoreload timers it is not possible
+ * Counter is count down, and with autoreload timers it is not possible
  * to detect how many interrupts passed while interrupts were blocked.
  * Also it is not possible to atomically add to the register.
  *
- * To work around this two timers are used, one is used as a reference
- * clock without reload, however we just disable the interrupt it
- * could generate.
+ * To work around this one of the timers is dedicated to be used as
+ * a restarting continuous reference clock without interrupt.
  *
- * Internally this keeps track of when the next timer should fire
+ * Internally this keeps track of when the timer should fire next,
  * and based on that time and the current value of the reference
- * clock a number is written into the timer count register to schedule
+ * clock a number is written into the timer interval register to schedule
  * the next event.
  */
-/* XXX update above comment */
 int
 sxitimer_tickintr(void *frame)
 {
+       struct sxitimer_softc   *sc = sxitimer_cd.cd_devs[0];
        uint32_t now, nextevent;
        int rc = 0;
 
@@ -277,31 +248,31 @@ sxitimer_tickintr(void *frame)
 
        now = sxitimer_readcnt32();
 
-       while ((int32_t)(now - sxitimer_tick_nextevt) < 0) {
-               sxitimer_tick_nextevt -= sxitimer_tick_tpi;
-               sxitimer_ticks_err_sum += sxitimer_ticks_err_cnt;
+       while ((int32_t)(now - sc->tick_nextevt) < 0) {
+               sc->tick_nextevt -= sc->tick_tpi;
+               sc->ticks_err_sum += sc->ticks_err_cnt;
 
-               while (sxitimer_ticks_err_sum  > hz) {
-                       sxitimer_tick_nextevt += 1;
-                       sxitimer_ticks_err_sum -= hz;
+               while (sc->ticks_err_sum  > hz) {
+                       sc->tick_nextevt += 1;
+                       sc->ticks_err_sum -= hz;
                }
 
                rc = 1;
                hardclock(frame);
        }
-       nextevent = now - sxitimer_tick_nextevt;
-       if (nextevent < 10 /* XXX */)
-               nextevent = 10;
+       nextevent = now - sc->tick_nextevt;
+       if (nextevent < TIMER_MIN_CYCLES)
+               nextevent = TIMER_MIN_CYCLES;
 
-       if (nextevent > sxitimer_tick_tpi) {
+       if (nextevent > sc->tick_tpi) {
                /*
                 * If interrupts are blocked too long, like during
                 * the root prompt or ddb, the timer can roll over,
                 * this will allow the system to continue to run
                 * even if time is lost.
                 */
-               nextevent = sxitimer_tick_tpi;
-               sxitimer_tick_nextevt = now;
+               nextevent = sc->tick_tpi;
+               sc->tick_nextevt = now;
        }
 
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
@@ -317,6 +288,7 @@ sxitimer_tickintr(void *frame)
 int
 sxitimer_statintr(void *frame)
 {
+       struct sxitimer_softc   *sc = sxitimer_cd.cd_devs[0];
        uint32_t now, nextevent, r;
        int rc = 0;
 
@@ -327,29 +299,23 @@ sxitimer_statintr(void *frame)
            TIMER_ISR, TIMER_IRQ(STATTIMER));
 
        now = sxitimer_readcnt32();
-       while ((int32_t)(now - sxitimer_stat_nextevt) < 0) {
+       while ((int32_t)(now - sc->stat_nextevt) < 0) {
                do {
-                       r = random() & (sxitimer_statvar -1);
+                       r = random() & (sc->statvar - 1);
                } while (r == 0); /* random == 0 not allowed */
-               sxitimer_stat_nextevt -= sxitimer_statmin + r;
+               sc->stat_nextevt -= sc->statmin + r;
                rc = 1;
                statclock(frame);
        }
 
-       nextevent = now - sxitimer_stat_nextevt;
+       nextevent = now - sc->stat_nextevt;
 
-       if (nextevent < 10 /* XXX */)
-               nextevent = 10;
+       if (nextevent < TIMER_MIN_CYCLES)
+               nextevent = TIMER_MIN_CYCLES;
 
-       if (nextevent > sxitimer_stat_tpi) {
-               /*
-                * If interrupts are blocked too long, like during
-                * the root prompt or ddb, the timer can roll over,
-                * this will allow the system to continue to run
-                * even if time is lost.
-                */
-               nextevent = sxitimer_stat_tpi;
-               sxitimer_stat_nextevt = now;
+       if (nextevent > sc->stat_tpi) {
+               nextevent = sc->stat_tpi;
+               sc->stat_nextevt = now;
        }
 
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
@@ -373,11 +339,6 @@ sxitimer_readcnt64(void)
            & CNT64_RL_EN)
                continue;
 
-       /*
-        * A10 usermanual doesn't mention anything about order, but fwiw
-        * iirc. A20 manual mentions that low should be read first.
-        */
-       /* XXX check above */
        low = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_LOW);
        high = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_HIGH);
        return (uint64_t)high << 32 | low;
@@ -405,25 +366,21 @@ sxitimer_delay(u_int usecs)
 void
 sxitimer_setstatclockrate(int newhz)
 {
+       struct sxitimer_softc   *sc = sxitimer_cd.cd_devs[0];
        int minint, statint, s;
        
        s = splstatclock();
 
-       statint = sxitimer_freq[STATTIMER] / newhz;
+       statint = STATFREQ / newhz;
        /* calculate largest 2^n which is smaller than just over half statint */
-       sxitimer_statvar = 0x40000000; /* really big power of two */
+       sc->statvar = 0x40000000; /* really big power of two */
        minint = statint / 2 + 100;
-       while (sxitimer_statvar > minint)
-               sxitimer_statvar >>= 1;
+       while (sc->statvar > minint)
+               sc->statvar >>= 1;
 
-       sxitimer_statmin = statint - (sxitimer_statvar >> 1);
+       sc->statmin = statint - (sc->statvar >> 1);
 
        splx(s);
-
-       /*
-        * XXX this allows the next stat timer to occur then it switches
-        * to the new frequency. Rather than switching instantly.
-        */
 }
 
 u_int

Reply via email to