summaryrefslogtreecommitdiffstats
path: root/target/linux/cns3xxx/patches-4.4/090-timers.patch
blob: 6f7713f209e8dd22d19940e0d722f1a2bcab0560 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
--- 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,7 +176,7 @@ 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,
+	.rating			= 300,
 	.cpumask		= cpu_all_mask,
 };
 
@@ -220,6 +221,32 @@ static void __init cns3xxx_init_twd(void
 	twd_local_timer_register(&cns3xx_twd_local_timer);
 }
 
+static cycle_t 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();
 }