cns3xxx: add support for kernel 4.19
[openwrt/openwrt.git] / target / linux / cns3xxx / patches-4.14 / 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 u64 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 }