aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/time-ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/time-ts.c')
-rw-r--r--arch/blackfin/kernel/time-ts.c205
1 files changed, 113 insertions, 92 deletions
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index 17c38c5b5b22..cb7a01d4f009 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -21,6 +21,7 @@
21#include <asm/blackfin.h> 21#include <asm/blackfin.h>
22#include <asm/time.h> 22#include <asm/time.h>
23#include <asm/gptimers.h> 23#include <asm/gptimers.h>
24#include <asm/nmi.h>
24 25
25/* Accelerators for sched_clock() 26/* Accelerators for sched_clock()
26 * convert from cycles(64bits) => nanoseconds (64bits) 27 * convert from cycles(64bits) => nanoseconds (64bits)
@@ -50,7 +51,11 @@
50 51
51static notrace cycle_t bfin_read_cycles(struct clocksource *cs) 52static notrace cycle_t bfin_read_cycles(struct clocksource *cs)
52{ 53{
54#ifdef CONFIG_CPU_FREQ
53 return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); 55 return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
56#else
57 return get_cycles();
58#endif
54} 59}
55 60
56static struct clocksource bfin_cs_cycles = { 61static struct clocksource bfin_cs_cycles = {
@@ -132,7 +137,6 @@ static int __init bfin_cs_gptimer0_init(void)
132# define bfin_cs_gptimer0_init() 137# define bfin_cs_gptimer0_init()
133#endif 138#endif
134 139
135
136#if defined(CONFIG_GPTMR0_CLOCKSOURCE) || defined(CONFIG_CYCLES_CLOCKSOURCE) 140#if defined(CONFIG_GPTMR0_CLOCKSOURCE) || defined(CONFIG_CYCLES_CLOCKSOURCE)
137/* prefer to use cycles since it has higher rating */ 141/* prefer to use cycles since it has higher rating */
138notrace unsigned long long sched_clock(void) 142notrace unsigned long long sched_clock(void)
@@ -145,47 +149,8 @@ notrace unsigned long long sched_clock(void)
145} 149}
146#endif 150#endif
147 151
148#ifdef CONFIG_CORE_TIMER_IRQ_L1
149__attribute__((l1_text))
150#endif
151irqreturn_t timer_interrupt(int irq, void *dev_id);
152
153static int bfin_timer_set_next_event(unsigned long, \
154 struct clock_event_device *);
155
156static void bfin_timer_set_mode(enum clock_event_mode, \
157 struct clock_event_device *);
158
159static struct clock_event_device clockevent_bfin = {
160#if defined(CONFIG_TICKSOURCE_GPTMR0)
161 .name = "bfin_gptimer0",
162 .rating = 300,
163 .irq = IRQ_TIMER0,
164#else
165 .name = "bfin_core_timer",
166 .rating = 350,
167 .irq = IRQ_CORETMR,
168#endif
169 .shift = 32,
170 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
171 .set_next_event = bfin_timer_set_next_event,
172 .set_mode = bfin_timer_set_mode,
173};
174
175static struct irqaction bfin_timer_irq = {
176#if defined(CONFIG_TICKSOURCE_GPTMR0)
177 .name = "Blackfin GPTimer0",
178#else
179 .name = "Blackfin CoreTimer",
180#endif
181 .flags = IRQF_DISABLED | IRQF_TIMER | \
182 IRQF_IRQPOLL | IRQF_PERCPU,
183 .handler = timer_interrupt,
184 .dev_id = &clockevent_bfin,
185};
186
187#if defined(CONFIG_TICKSOURCE_GPTMR0) 152#if defined(CONFIG_TICKSOURCE_GPTMR0)
188static int bfin_timer_set_next_event(unsigned long cycles, 153static int bfin_gptmr0_set_next_event(unsigned long cycles,
189 struct clock_event_device *evt) 154 struct clock_event_device *evt)
190{ 155{
191 disable_gptimers(TIMER0bit); 156 disable_gptimers(TIMER0bit);
@@ -196,7 +161,7 @@ static int bfin_timer_set_next_event(unsigned long cycles,
196 return 0; 161 return 0;
197} 162}
198 163
199static void bfin_timer_set_mode(enum clock_event_mode mode, 164static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
200 struct clock_event_device *evt) 165 struct clock_event_device *evt)
201{ 166{
202 switch (mode) { 167 switch (mode) {
@@ -224,25 +189,65 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
224 } 189 }
225} 190}
226 191
227static void bfin_timer_ack(void) 192static void bfin_gptmr0_ack(void)
228{ 193{
229 set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0); 194 set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0);
230} 195}
231 196
232static void __init bfin_timer_init(void) 197static void __init bfin_gptmr0_init(void)
233{ 198{
234 disable_gptimers(TIMER0bit); 199 disable_gptimers(TIMER0bit);
235} 200}
236 201
237static unsigned long __init bfin_clockevent_check(void) 202#ifdef CONFIG_CORE_TIMER_IRQ_L1
203__attribute__((l1_text))
204#endif
205irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id)
238{ 206{
239 setup_irq(IRQ_TIMER0, &bfin_timer_irq); 207 struct clock_event_device *evt = dev_id;
240 return get_sclk(); 208 smp_mb();
209 evt->event_handler(evt);
210 bfin_gptmr0_ack();
211 return IRQ_HANDLED;
241} 212}
242 213
243#else /* CONFIG_TICKSOURCE_CORETMR */ 214static struct irqaction gptmr0_irq = {
215 .name = "Blackfin GPTimer0",
216 .flags = IRQF_DISABLED | IRQF_TIMER | \
217 IRQF_IRQPOLL | IRQF_PERCPU,
218 .handler = bfin_gptmr0_interrupt,
219};
244 220
245static int bfin_timer_set_next_event(unsigned long cycles, 221static struct clock_event_device clockevent_gptmr0 = {
222 .name = "bfin_gptimer0",
223 .rating = 300,
224 .irq = IRQ_TIMER0,
225 .shift = 32,
226 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
227 .set_next_event = bfin_gptmr0_set_next_event,
228 .set_mode = bfin_gptmr0_set_mode,
229};
230
231static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt)
232{
233 unsigned long clock_tick;
234
235 clock_tick = get_sclk();
236 evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
237 evt->max_delta_ns = clockevent_delta2ns(-1, evt);
238 evt->min_delta_ns = clockevent_delta2ns(100, evt);
239
240 evt->cpumask = cpumask_of(0);
241
242 clockevents_register_device(evt);
243}
244#endif /* CONFIG_TICKSOURCE_GPTMR0 */
245
246#if defined(CONFIG_TICKSOURCE_CORETMR)
247/* per-cpu local core timer */
248static DEFINE_PER_CPU(struct clock_event_device, coretmr_events);
249
250static int bfin_coretmr_set_next_event(unsigned long cycles,
246 struct clock_event_device *evt) 251 struct clock_event_device *evt)
247{ 252{
248 bfin_write_TCNTL(TMPWR); 253 bfin_write_TCNTL(TMPWR);
@@ -253,7 +258,7 @@ static int bfin_timer_set_next_event(unsigned long cycles,
253 return 0; 258 return 0;
254} 259}
255 260
256static void bfin_timer_set_mode(enum clock_event_mode mode, 261static void bfin_coretmr_set_mode(enum clock_event_mode mode,
257 struct clock_event_device *evt) 262 struct clock_event_device *evt)
258{ 263{
259 switch (mode) { 264 switch (mode) {
@@ -285,19 +290,13 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
285 } 290 }
286} 291}
287 292
288static void bfin_timer_ack(void) 293void bfin_coretmr_init(void)
289{
290}
291
292static void __init bfin_timer_init(void)
293{ 294{
294 /* power up the timer, but don't enable it just yet */ 295 /* power up the timer, but don't enable it just yet */
295 bfin_write_TCNTL(TMPWR); 296 bfin_write_TCNTL(TMPWR);
296 CSYNC(); 297 CSYNC();
297 298
298 /* 299 /* the TSCALE prescaler counter. */
299 * the TSCALE prescaler counter.
300 */
301 bfin_write_TSCALE(TIME_SCALE - 1); 300 bfin_write_TSCALE(TIME_SCALE - 1);
302 bfin_write_TPERIOD(0); 301 bfin_write_TPERIOD(0);
303 bfin_write_TCOUNT(0); 302 bfin_write_TCOUNT(0);
@@ -305,48 +304,54 @@ static void __init bfin_timer_init(void)
305 CSYNC(); 304 CSYNC();
306} 305}
307 306
308static unsigned long __init bfin_clockevent_check(void) 307#ifdef CONFIG_CORE_TIMER_IRQ_L1
309{ 308__attribute__((l1_text))
310 setup_irq(IRQ_CORETMR, &bfin_timer_irq); 309#endif
311 return get_cclk() / TIME_SCALE; 310irqreturn_t bfin_coretmr_interrupt(int irq, void *dev_id)
312}
313
314void __init setup_core_timer(void)
315{ 311{
316 bfin_timer_init(); 312 int cpu = smp_processor_id();
317 bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL); 313 struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);
318}
319#endif /* CONFIG_TICKSOURCE_GPTMR0 */
320 314
321/*
322 * timer_interrupt() needs to keep up the real-time clock,
323 * as well as call the "do_timer()" routine every clocktick
324 */
325irqreturn_t timer_interrupt(int irq, void *dev_id)
326{
327 struct clock_event_device *evt = dev_id;
328 smp_mb(); 315 smp_mb();
329 evt->event_handler(evt); 316 evt->event_handler(evt);
330 bfin_timer_ack();
331 return IRQ_HANDLED;
332}
333
334static int __init bfin_clockevent_init(void)
335{
336 unsigned long timer_clk;
337 317
338 timer_clk = bfin_clockevent_check(); 318 touch_nmi_watchdog();
339 319
340 bfin_timer_init(); 320 return IRQ_HANDLED;
321}
341 322
342 clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); 323static struct irqaction coretmr_irq = {
343 clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin); 324 .name = "Blackfin CoreTimer",
344 clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin); 325 .flags = IRQF_DISABLED | IRQF_TIMER | \
345 clockevent_bfin.cpumask = cpumask_of(0); 326 IRQF_IRQPOLL | IRQF_PERCPU,
346 clockevents_register_device(&clockevent_bfin); 327 .handler = bfin_coretmr_interrupt,
328};
347 329
348 return 0; 330void bfin_coretmr_clockevent_init(void)
331{
332 unsigned long clock_tick;
333 unsigned int cpu = smp_processor_id();
334 struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);
335
336 evt->name = "bfin_core_timer";
337 evt->rating = 350;
338 evt->irq = -1;
339 evt->shift = 32;
340 evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
341 evt->set_next_event = bfin_coretmr_set_next_event;
342 evt->set_mode = bfin_coretmr_set_mode;
343
344 clock_tick = get_cclk() / TIME_SCALE;
345 evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
346 evt->max_delta_ns = clockevent_delta2ns(-1, evt);
347 evt->min_delta_ns = clockevent_delta2ns(100, evt);
348
349 evt->cpumask = cpumask_of(cpu);
350
351 clockevents_register_device(evt);
349} 352}
353#endif /* CONFIG_TICKSOURCE_CORETMR */
354
350 355
351void __init time_init(void) 356void __init time_init(void)
352{ 357{
@@ -370,5 +375,21 @@ void __init time_init(void)
370 375
371 bfin_cs_cycles_init(); 376 bfin_cs_cycles_init();
372 bfin_cs_gptimer0_init(); 377 bfin_cs_gptimer0_init();
373 bfin_clockevent_init(); 378
379#if defined(CONFIG_TICKSOURCE_CORETMR)
380 bfin_coretmr_init();
381 setup_irq(IRQ_CORETMR, &coretmr_irq);
382 bfin_coretmr_clockevent_init();
383#endif
384
385#if defined(CONFIG_TICKSOURCE_GPTMR0)
386 bfin_gptmr0_init();
387 setup_irq(IRQ_TIMER0, &gptmr0_irq);
388 gptmr0_irq.dev_id = &clockevent_gptmr0;
389 bfin_gptmr0_clockevent_init(&clockevent_gptmr0);
390#endif
391
392#if !defined(CONFIG_TICKSOURCE_CORETMR) && !defined(CONFIG_TICKSOURCE_GPTMR0)
393# error at least one clock event device is required
394#endif
374} 395}