On my Olimex A10s-Olinuxino Micro, time drifts quite fast (something
of the order of a second per minute).  The driver is written to use a
32kHz clock.  The device tree on both sun4i and sun5i only references
the 24MHz clock though.  And the A10s and A13 datasheets don't
document the settings for using the 32kHz clock.  The diff below
switches the driver over to the 24MHz clock.  This could use some
additional testing on other boards, especially those with the A10 SoC
such as the original Cubieboard.


Index: arch/armv7/sunxi/sunxireg.h
===================================================================
RCS file: /cvs/src/sys/arch/armv7/sunxi/sunxireg.h,v
retrieving revision 1.8
diff -u -p -r1.8 sunxireg.h
--- arch/armv7/sunxi/sunxireg.h 2 Feb 2016 21:40:47 -0000       1.8
+++ arch/armv7/sunxi/sunxireg.h 9 Oct 2016 16:03:38 -0000
@@ -37,9 +37,9 @@
 #define        SXICMS4(sc, reg, mask, bits)                                    
\
        SXIWRITE4((sc), (reg), (SXIREAD4((sc), (reg)) & ~(mask)) | (bits))
 
-#define        TIMER0_FREQUENCY        (32768)
-#define        TIMER1_FREQUENCY        (32768)
-#define        TIMER2_FREQUENCY        (32768)
+#define        TIMER0_FREQUENCY        (24000000)
+#define        TIMER1_FREQUENCY        (24000000)
+#define        TIMER2_FREQUENCY        (24000000)
 #define        COUNTER_FREQUENCY       (24000000)
 
 /* SRAM Controller / System Control */
Index: arch/armv7/sunxi/sxitimer.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/sunxi/sxitimer.c,v
retrieving revision 1.6
diff -u -p -r1.6 sxitimer.c
--- arch/armv7/sunxi/sxitimer.c 18 Jul 2016 19:22:45 -0000      1.6
+++ arch/armv7/sunxi/sxitimer.c 9 Oct 2016 16:03:45 -0000
@@ -52,13 +52,9 @@
 #define        CNT64_CLR_EN            (1 << 0) /* clear enable */
 #define        CNT64_RL_EN             (1 << 1) /* read latch enable */
 
-#define        LOSC_CTRL               0x100
-#define        OSC32K_SRC_SEL          (1 << 0)
-
 #define        TIMER_ENABLE            (1 << 0)
 #define        TIMER_RELOAD            (1 << 1)
 #define        TIMER_CLK_SRC_MASK      (3 << 2)
-#define        TIMER_LSOSC             (0 << 2)
 #define        TIMER_OSC24M            (1 << 2)
 #define        TIMER_PLL6_6            (2 << 2)
 #define        TIMER_PRESC_1           (0 << 4)
@@ -132,7 +128,7 @@ void
 sxitimer_attach(struct device *parent, struct device *self, void *args)
 {
        struct armv7_attach_args *aa = args;
-       uint32_t freq, ival, now, cr;
+       uint32_t freq, ival, now;
        int unit = self->dv_unit;
 
        if (unit != 0)
@@ -151,11 +147,6 @@ sxitimer_attach(struct device *parent, s
            & 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 */
@@ -163,8 +154,7 @@ skip_init:
 
        /* stop timer, and set clk src */
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
-           TIMER_CTRL(unit),
-           freq == 24000000 ? TIMER_OSC24M : TIMER_LSOSC);
+           TIMER_CTRL(unit), TIMER_OSC24M);
 
        switch (unit) { /* XXX more XXXXTIMER magic for less lines? */
        case TICKTIMER:
@@ -217,7 +207,7 @@ skip_init:
 void
 sxitimer_cpu_initclocks(void)
 {
-       uint32_t isr, ier;
+       uint32_t isr, ier, ctrl;
 
        /* establish interrupts */
        arm_intr_establish(sxitimer_irq[TICKTIMER], IPL_CLOCK,
@@ -236,17 +226,23 @@ sxitimer_cpu_initclocks(void)
        bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_IER, ier);
 
        /* enable timers */
+       ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh,
+           TIMER_CTRL(CNTRTIMER));
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
            TIMER_CTRL(CNTRTIMER),
-           TIMER_ENABLE | TIMER_RELOAD | TIMER_CONTINOUS);
+           ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_CONTINOUS);
 
+       ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh,
+           TIMER_CTRL(STATTIMER));
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
            TIMER_CTRL(STATTIMER),
-           TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT);
+           ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT);
 
+       ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh,
+           TIMER_CTRL(TICKTIMER));
        bus_space_write_4(sxitimer_iot, sxitimer_ioh,
            TIMER_CTRL(TICKTIMER),
-           TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT);
+           ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT);
 }
 
 /* 

Reply via email to