cns3xxx: add support for kernel 4.19
[openwrt/openwrt.git] / target / linux / cns3xxx / patches-4.19 / 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,8 +176,8 @@ 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 - .cpumask = cpu_all_mask,
26 + .rating = 300,
27 + .cpumask = cpu_possible_mask,
28 };
29
30 static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
31 @@ -220,6 +221,32 @@ static void __init cns3xxx_init_twd(void
32 twd_local_timer_register(&cns3xx_twd_local_timer);
33 }
34
35 +static u64 cns3xxx_get_cycles(struct clocksource *cs)
36 +{
37 + u64 val;
38 +
39 + val = readl(cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
40 + val &= 0xffff;
41 +
42 + return ((val << 32) | readl(cns3xxx_tmr1 + TIMER_FREERUN_OFFSET));
43 +}
44 +
45 +static struct clocksource clocksource_cns3xxx = {
46 + .name = "freerun",
47 + .rating = 200,
48 + .read = cns3xxx_get_cycles,
49 + .mask = CLOCKSOURCE_MASK(48),
50 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
51 +};
52 +
53 +static void __init cns3xxx_clocksource_init(void)
54 +{
55 + /* Reset the FreeRunning counter */
56 + writel((1 << 16), cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
57 +
58 + clocksource_register_khz(&clocksource_cns3xxx, 100);
59 +}
60 +
61 /*
62 * Set up the clock source and clock events devices
63 */
64 @@ -237,13 +264,12 @@ static void __init __cns3xxx_timer_init(
65 /* stop free running timer3 */
66 writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
67
68 - /* timer1 */
69 - writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
70 - writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
71 -
72 writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
73 writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
74
75 + val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ;
76 + writel(val, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
77 +
78 /* mask irq, non-mask timer1 overflow */
79 irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
80 irq_mask &= ~(1 << 2);
81 @@ -255,23 +281,9 @@ static void __init __cns3xxx_timer_init(
82 val |= (1 << 9);
83 writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
84
85 - /* timer2 */
86 - writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
87 - writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
88 -
89 - /* mask irq */
90 - irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
91 - irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
92 - writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
93 -
94 - /* down counter */
95 - val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
96 - val |= (1 << 10);
97 - writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
98 -
99 - /* Make irqs happen for the system timer */
100 setup_irq(timer_irq, &cns3xxx_timer_irq);
101
102 + cns3xxx_clocksource_init();
103 cns3xxx_clockevents_init(timer_irq);
104 cns3xxx_init_twd();
105 }