06251356d2a7429852594289c7e2ca3a929f09a5
[openwrt/svn-archive/archive.git] / target / linux / gemini / patches-3.18 / 160-gemini-timers.patch
1 --- a/arch/arm/mach-gemini/time.c 2015-03-25 23:06:03.188317455 +0200
2 +++ b/arch/arm/mach-gemini/time.c 2015-03-25 23:06:24.417315486 +0200
3 @@ -15,15 +15,18 @@
4 #include <asm/mach/time.h>
5 #include <linux/clockchips.h>
6 #include <linux/clocksource.h>
7 +#include <linux/sched_clock.h>
8
9 /*
10 * Register definitions for the timers
11 */
12 -#define TIMER_COUNT(BASE_ADDR) (BASE_ADDR + 0x00)
13 -#define TIMER_LOAD(BASE_ADDR) (BASE_ADDR + 0x04)
14 -#define TIMER_MATCH1(BASE_ADDR) (BASE_ADDR + 0x08)
15 -#define TIMER_MATCH2(BASE_ADDR) (BASE_ADDR + 0x0C)
16 -#define TIMER_CR(BASE_ADDR) (BASE_ADDR + 0x30)
17 +#define TIMER_COUNT(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x00)
18 +#define TIMER_LOAD(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x04)
19 +#define TIMER_MATCH1(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x08)
20 +#define TIMER_MATCH2(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x0C)
21 +#define TIMER_CR(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x30)
22 +#define TIMER_INTR_STATE(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x34)
23 +#define TIMER_INTR_MASK(BASE_ADDR) (IO_ADDRESS(BASE_ADDR) + 0x38)
24
25 #define TIMER_1_CR_ENABLE (1 << 0)
26 #define TIMER_1_CR_CLOCK (1 << 1)
27 @@ -34,27 +37,38 @@
28 #define TIMER_3_CR_ENABLE (1 << 6)
29 #define TIMER_3_CR_CLOCK (1 << 7)
30 #define TIMER_3_CR_INT (1 << 8)
31 +#define TIMER_1_CR_UPDOWN (1 << 9)
32 +#define TIMER_2_CR_UPDOWN (1 << 10)
33 +#define TIMER_3_CR_UPDOWN (1 << 11)
34 +
35 +#define TIMER_1_INT_MATCH1 (1 << 0)
36 +#define TIMER_1_INT_MATCH2 (1 << 1)
37 +#define TIMER_1_INT_OVERFLOW (1 << 2)
38 +#define TIMER_2_INT_MATCH1 (1 << 3)
39 +#define TIMER_2_INT_MATCH2 (1 << 4)
40 +#define TIMER_2_INT_OVERFLOW (1 << 5)
41 +#define TIMER_3_INT_MATCH1 (1 << 6)
42 +#define TIMER_3_INT_MATCH2 (1 << 7)
43 +#define TIMER_3_INT_OVERFLOW (1 << 8)
44 +#define TIMER_INT_ALL_MASK 0x1ff
45
46 static unsigned int tick_rate;
47
48 +static u64 notrace gemini_read_sched_clock(void)
49 +{
50 + return readl(TIMER_COUNT(GEMINI_TIMER3_BASE));
51 +}
52 +
53 static int gemini_timer_set_next_event(unsigned long cycles,
54 struct clock_event_device *evt)
55 {
56 u32 cr;
57
58 - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
59 -
60 - /* This may be overdoing it, feel free to test without this */
61 - cr &= ~TIMER_2_CR_ENABLE;
62 - cr &= ~TIMER_2_CR_INT;
63 - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
64 -
65 - /* Set next event */
66 - writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
67 - writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
68 - cr |= TIMER_2_CR_ENABLE;
69 - cr |= TIMER_2_CR_INT;
70 - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
71 + /* Setup the match register */
72 + cr = readl(TIMER_COUNT(GEMINI_TIMER1_BASE));
73 + writel(cr + cycles, TIMER_MATCH1(GEMINI_TIMER1_BASE));
74 + if (readl(TIMER_COUNT(GEMINI_TIMER1_BASE)) - cr > cycles)
75 + return -ETIME;
76
77 return 0;
78 }
79 @@ -66,48 +80,68 @@
80 u32 cr;
81
82 switch (mode) {
83 - case CLOCK_EVT_MODE_PERIODIC:
84 - /* Start the timer */
85 - writel(period,
86 - TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
87 - writel(period,
88 - TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
89 - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
90 - cr |= TIMER_2_CR_ENABLE;
91 - cr |= TIMER_2_CR_INT;
92 - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
93 + case CLOCK_EVT_MODE_PERIODIC:
94 + /* Stop timer and interrupt. */
95 + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
96 + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
97 + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
98 +
99 + /* Setup timer to fire at 1/HZ intervals. */
100 + cr = 0xffffffff - (period - 1);
101 + writel(cr, TIMER_COUNT(GEMINI_TIMER1_BASE));
102 + writel(cr, TIMER_LOAD(GEMINI_TIMER1_BASE));
103 +
104 + /* enable interrupt on overflaw */
105 + cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
106 + cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
107 + cr |= TIMER_1_INT_OVERFLOW;
108 + writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
109 +
110 + /* start the timer */
111 + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
112 + cr |= TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
113 + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
114 break;
115 +
116 case CLOCK_EVT_MODE_ONESHOT:
117 case CLOCK_EVT_MODE_UNUSED:
118 - case CLOCK_EVT_MODE_SHUTDOWN:
119 + case CLOCK_EVT_MODE_SHUTDOWN:
120 + /* Stop timer and interrupt. */
121 + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
122 + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
123 + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
124 +
125 + /* Setup counter start from 0 */
126 + writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
127 + writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
128 +
129 + /* enable interrupt */
130 + cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
131 + cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
132 + cr |= TIMER_1_INT_MATCH1;
133 + writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
134 +
135 + /* start the timer */
136 + cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
137 + cr |= TIMER_1_CR_ENABLE;
138 + writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
139 + break;
140 +
141 case CLOCK_EVT_MODE_RESUME:
142 - /*
143 - * Disable also for oneshot: the set_next() call will
144 - * arm the timer instead.
145 - */
146 - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
147 - cr &= ~TIMER_2_CR_ENABLE;
148 - cr &= ~TIMER_2_CR_INT;
149 - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
150 break;
151 - default:
152 - break;
153 }
154 }
155
156 -/* Use TIMER2 as clock event */
157 static struct clock_event_device gemini_clockevent = {
158 - .name = "TIMER2",
159 - .rating = 300, /* Reasonably fast and accurate clock event */
160 - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
161 - .set_next_event = gemini_timer_set_next_event,
162 - .set_mode = gemini_timer_set_mode,
163 + .name = "gemini_timer_1",
164 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
165 + .shift = 32,
166 + .rating = 300,
167 + .set_next_event = gemini_timer_set_next_event,
168 + .set_mode = gemini_timer_set_mode,
169 };
170
171 -/*
172 - * IRQ handler for the timer
173 - */
174 -static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
175 +static irqreturn_t gemini_timer_intr(int irq, void *dev_id)
176 {
177 struct clock_event_device *evt = &gemini_clockevent;
178
179 @@ -116,14 +150,11 @@
180 }
181
182 static struct irqaction gemini_timer_irq = {
183 - .name = "Gemini Timer Tick",
184 - .flags = IRQF_TIMER,
185 - .handler = gemini_timer_interrupt,
186 + .name = "gemini timer 1",
187 + .flags = IRQF_DISABLED | IRQF_TIMER,
188 + .handler = gemini_timer_intr,
189 };
190
191 -/*
192 - * Set up timer interrupt, and return the current time in seconds.
193 - */
194 void __init gemini_timer_init(void)
195 {
196 u32 reg_v;
197 @@ -151,20 +182,35 @@
198 }
199
200 /*
201 - * Make irqs happen for the system timer
202 + * Reset the interrupt mask and status
203 */
204 - setup_irq(IRQ_TIMER2, &gemini_timer_irq);
205 + writel(TIMER_INT_ALL_MASK, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
206 + writel(0, TIMER_INTR_STATE(GEMINI_TIMER_BASE));
207 + writel(TIMER_1_CR_UPDOWN | TIMER_3_CR_ENABLE | TIMER_3_CR_UPDOWN,
208 + TIMER_CR(GEMINI_TIMER_BASE));
209
210 - /* Enable and use TIMER1 as clock source */
211 - writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
212 - writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
213 - writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
214 - if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
215 - "TIMER1", tick_rate, 300, 32,
216 - clocksource_mmio_readl_up))
217 - pr_err("timer: failed to initialize gemini clock source\n");
218 + /*
219 + * Setup free-running clocksource timer (interrupts
220 + * disabled.)
221 + */
222 + writel(0, TIMER_COUNT(GEMINI_TIMER3_BASE));
223 + writel(0, TIMER_LOAD(GEMINI_TIMER3_BASE));
224 + writel(0, TIMER_MATCH1(GEMINI_TIMER3_BASE));
225 + writel(0, TIMER_MATCH2(GEMINI_TIMER3_BASE));
226 + clocksource_mmio_init(TIMER_COUNT(GEMINI_TIMER3_BASE),
227 + "gemini_clocksource", tick_rate,
228 + 300, 32, clocksource_mmio_readl_up);
229 + sched_clock_register(gemini_read_sched_clock, 32, tick_rate);
230
231 - /* Configure and register the clockevent */
232 + /*
233 + * Setup clockevent timer (interrupt-driven.)
234 + */
235 + writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
236 + writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
237 + writel(0, TIMER_MATCH1(GEMINI_TIMER1_BASE));
238 + writel(0, TIMER_MATCH2(GEMINI_TIMER1_BASE));
239 + setup_irq(IRQ_TIMER1, &gemini_timer_irq);
240 + gemini_clockevent.cpumask = cpumask_of(0);
241 clockevents_config_and_register(&gemini_clockevent, tick_rate,
242 1, 0xffffffff);
243 }