OpenWrt – Rev 1

Subversion Repositories:
Rev:
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -138,6 +138,7 @@ static int cns3xxx_set_oneshot(struct cl
 
        /* period set, and timer enabled in 'next_event' hook */
        ctrl |= (1 << 2) | (1 << 9);
+       writel(0, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
        writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
        return 0;
 }
@@ -148,7 +149,7 @@ static int cns3xxx_set_periodic(struct c
        int pclk = cns3xxx_cpu_clock() / 8;
        int reload;
 
-       reload = pclk * 20 / (3 * HZ) * 0x25000;
+       reload = pclk * 1000000 / HZ;
        writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
        ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
        writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
@@ -175,8 +176,8 @@ static struct clock_event_device cns3xxx
        .set_state_oneshot      = cns3xxx_set_oneshot,
        .tick_resume            = cns3xxx_shutdown,
        .set_next_event         = cns3xxx_timer_set_next_event,
-       .rating                 = 350,
-       .cpumask                = cpu_all_mask,
+       .rating                 = 300,
+       .cpumask                = cpu_possible_mask,
 };
 
 static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
@@ -220,6 +221,32 @@ static void __init cns3xxx_init_twd(void
        twd_local_timer_register(&cns3xx_twd_local_timer);
 }
 
+static u64 cns3xxx_get_cycles(struct clocksource *cs)
+{
+  u64 val;
+
+  val = readl(cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
+  val &= 0xffff;
+
+  return ((val << 32) | readl(cns3xxx_tmr1 + TIMER_FREERUN_OFFSET));
+}
+
+static struct clocksource clocksource_cns3xxx = {
+       .name = "freerun",
+       .rating = 200,
+       .read = cns3xxx_get_cycles,
+       .mask = CLOCKSOURCE_MASK(48),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init cns3xxx_clocksource_init(void)
+{
+       /* Reset the FreeRunning counter */
+       writel((1 << 16), cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
+
+       clocksource_register_khz(&clocksource_cns3xxx, 100);
+}
+
 /*
  * Set up the clock source and clock events devices
  */
@@ -237,13 +264,12 @@ static void __init __cns3xxx_timer_init(
        /* stop free running timer3 */
        writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
 
-       /* timer1 */
-       writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
-       writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
-
        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
 
+       val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ;
+       writel(val, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
+
        /* mask irq, non-mask timer1 overflow */
        irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
        irq_mask &= ~(1 << 2);
@@ -255,23 +281,9 @@ static void __init __cns3xxx_timer_init(
        val |= (1 << 9);
        writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 
-       /* timer2 */
-       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
-       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
-
-       /* mask irq */
-       irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
-       irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
-       writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
-
-       /* down counter */
-       val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
-       val |= (1 << 10);
-       writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
-
-       /* Make irqs happen for the system timer */
        setup_irq(timer_irq, &cns3xxx_timer_irq);
 
+       cns3xxx_clocksource_init();
        cns3xxx_clockevents_init(timer_irq);
        cns3xxx_init_twd();
 }