Merge pull request #580 from wigyori/cc-libpcap
[15.05/openwrt.git] / target / linux / cns3xxx / patches-3.18 / 090-timers.patch
1 --- a/arch/arm/mach-cns3xxx/core.c
2 +++ b/arch/arm/mach-cns3xxx/core.c
3 @@ -135,12 +135,13 @@ static void cns3xxx_timer_set_mode(enum
4  
5         switch (mode) {
6         case CLOCK_EVT_MODE_PERIODIC:
7 -               reload = pclk * 20 / (3 * HZ) * 0x25000;
8 +               reload = pclk * 1000000 / HZ;
9                 writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
10                 ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
11                 break;
12         case CLOCK_EVT_MODE_ONESHOT:
13                 /* period set, and timer enabled in 'next_event' hook */
14 +               writel(0, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
15                 ctrl |= (1 << 2) | (1 << 9);
16                 break;
17         case CLOCK_EVT_MODE_UNUSED:
18 @@ -168,7 +169,7 @@ static struct clock_event_device cns3xxx
19         .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
20         .set_mode       = cns3xxx_timer_set_mode,
21         .set_next_event = cns3xxx_timer_set_next_event,
22 -       .rating         = 350,
23 +       .rating         = 300,
24         .cpumask        = cpu_all_mask,
25  };
26  
27 @@ -215,6 +216,35 @@ static void __init cns3xxx_init_twd(void
28  #endif
29  }
30  
31 +static cycle_t cns3xxx_get_cycles(struct clocksource *cs)
32 +{
33 +  u64 val;
34 +
35 +  val = readl(cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
36 +  val &= 0xffff;
37 +
38 +  return ((val << 32) | readl(cns3xxx_tmr1 + TIMER_FREERUN_OFFSET));
39 +}
40 +
41 +static struct clocksource clocksource_cns3xxx = {
42 +       .name = "freerun",
43 +       .rating = 200,
44 +       .read = cns3xxx_get_cycles,
45 +       .mask = CLOCKSOURCE_MASK(48),
46 +       .shift  = 16,
47 +       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
48 +};
49 +
50 +static void __init cns3xxx_clocksource_init(void)
51 +{
52 +       /* Reset the FreeRunning counter */
53 +       writel((1 << 16), cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
54 +
55 +       clocksource_cns3xxx.mult =
56 +               clocksource_khz2mult(100, clocksource_cns3xxx.shift);
57 +       clocksource_register(&clocksource_cns3xxx);
58 +}
59 +
60  /*
61   * Set up the clock source and clock events devices
62   */
63 @@ -232,13 +262,12 @@ static void __init __cns3xxx_timer_init(
64         /* stop free running timer3 */
65         writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
66  
67 -       /* timer1 */
68 -       writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
69 -       writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
70 -
71         writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
72         writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
73  
74 +       val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ;
75 +       writel(val, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
76 +
77         /* mask irq, non-mask timer1 overflow */
78         irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
79         irq_mask &= ~(1 << 2);
80 @@ -250,23 +279,9 @@ static void __init __cns3xxx_timer_init(
81         val |= (1 << 9);
82         writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
83  
84 -       /* timer2 */
85 -       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
86 -       writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
87 -
88 -       /* mask irq */
89 -       irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
90 -       irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
91 -       writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
92 -
93 -       /* down counter */
94 -       val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
95 -       val |= (1 << 10);
96 -       writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
97 -
98 -       /* Make irqs happen for the system timer */
99         setup_irq(timer_irq, &cns3xxx_timer_irq);
100  
101 +       cns3xxx_clocksource_init();
102         cns3xxx_clockevents_init(timer_irq);
103         cns3xxx_init_twd();
104  }