octeon: only copy sysupgrade file if present
[oweals/openwrt.git] / target / linux / cns3xxx / patches-4.4 / 090-timers.patch
1 --- a/arch/arm/mach-cns3xxx/core.c
2 +++ b/arch/arm/mach-cns3xxx/core.c
3 @@ -138,6 +138,7 @@ static int cns3xxx_set_oneshot(struct cl
4  
5         /* period set, and timer enabled in 'next_event' hook */
6         ctrl |= (1 << 2) | (1 << 9);
7 +       writel(0, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
8         writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
9         return 0;
10  }
11 @@ -148,7 +149,7 @@ static int cns3xxx_set_periodic(struct c
12         int pclk = cns3xxx_cpu_clock() / 8;
13         int reload;
14  
15 -       reload = pclk * 20 / (3 * HZ) * 0x25000;
16 +       reload = pclk * 1000000 / HZ;
17         writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
18         ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
19         writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
20 @@ -175,7 +176,7 @@ static struct clock_event_device cns3xxx
21         .set_state_oneshot      = cns3xxx_set_oneshot,
22         .tick_resume            = cns3xxx_shutdown,
23         .set_next_event         = cns3xxx_timer_set_next_event,
24 -       .rating                 = 350,
25 +       .rating                 = 300,
26         .cpumask                = cpu_all_mask,
27  };
28  
29 @@ -220,6 +221,32 @@ static void __init cns3xxx_init_twd(void
30         twd_local_timer_register(&cns3xx_twd_local_timer);
31  }
32  
33 +static cycle_t cns3xxx_get_cycles(struct clocksource *cs)
34 +{
35 +  u64 val;
36 +
37 +  val = readl(cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
38 +  val &= 0xffff;
39 +
40 +  return ((val << 32) | readl(cns3xxx_tmr1 + TIMER_FREERUN_OFFSET));
41 +}
42 +
43 +static struct clocksource clocksource_cns3xxx = {
44 +       .name = "freerun",
45 +       .rating = 200,
46 +       .read = cns3xxx_get_cycles,
47 +       .mask = CLOCKSOURCE_MASK(48),
48 +       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
49 +};
50 +
51 +static void __init cns3xxx_clocksource_init(void)
52 +{
53 +       /* Reset the FreeRunning counter */
54 +       writel((1 << 16), cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
55 +
56 +       clocksource_register_khz(&clocksource_cns3xxx, 100);
57 +}
58 +
59  /*
60   * Set up the clock source and clock events devices
61   */
62 @@ -237,13 +264,12 @@ static void __init __cns3xxx_timer_init(
63         /* stop free running timer3 */
64         writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
65  
66 -       /* timer1 */
67 -       writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
68 -       writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
69 -
70         writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
71         writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
72  
73 +       val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ;
74 +       writel(val, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
75 +
76         /* mask irq, non-mask timer1 overflow */
77         irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
78         irq_mask &= ~(1 << 2);
79 @@ -255,23 +281,9 @@ static void __init __cns3xxx_timer_init(
80         val |= (1 << 9);
81         writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
82  
83 -       /* timer2 */
84 -       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
85 -       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
86 -
87 -       /* mask irq */
88 -       irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
89 -       irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
90 -       writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
91 -
92 -       /* down counter */
93 -       val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
94 -       val |= (1 << 10);
95 -       writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
96 -
97 -       /* Make irqs happen for the system timer */
98         setup_irq(timer_irq, &cns3xxx_timer_irq);
99  
100 +       cns3xxx_clocksource_init();
101         cns3xxx_clockevents_init(timer_irq);
102         cns3xxx_init_twd();
103  }