aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-clps711x
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2013-05-13 13:07:32 -0400
committerOlof Johansson <olof@lixom.net>2013-06-11 18:47:35 -0400
commitc99f72addbf5c0ad37d5a9b26f99208464d35f5c (patch)
treef86803ce60ba8969740b51e71aa26d8685d5468a /arch/arm/mach-clps711x
parentd0ad52a6fa9018d18076a887898f7912ae91f246 (diff)
ARM: clps711x: Add clocksource framework
Signed-off-by: Alexander Shiyan <shc_work@mail.ru> Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-clps711x')
-rw-r--r--arch/arm/mach-clps711x/common.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 768d41c68cea..bd658398a819 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -27,12 +27,14 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/clkdev.h> 28#include <linux/clkdev.h>
29#include <linux/clockchips.h> 29#include <linux/clockchips.h>
30#include <linux/clocksource.h>
30#include <linux/clk-provider.h> 31#include <linux/clk-provider.h>
31 32
32#include <asm/exception.h> 33#include <asm/exception.h>
33#include <asm/mach/irq.h> 34#include <asm/mach/irq.h>
34#include <asm/mach/map.h> 35#include <asm/mach/map.h>
35#include <asm/mach/time.h> 36#include <asm/mach/time.h>
37#include <asm/sched_clock.h>
36#include <asm/system_misc.h> 38#include <asm/system_misc.h>
37 39
38#include <mach/hardware.h> 40#include <mach/hardware.h>
@@ -251,13 +253,32 @@ asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs)
251 handle_IRQ(fls16(irqstat) + 16, regs); 253 handle_IRQ(fls16(irqstat) + 16, regs);
252} 254}
253 255
256static u32 notrace clps711x_sched_clock_read(void)
257{
258 return ~readw_relaxed(CLPS711X_VIRT_BASE + TC1D);
259}
260
254static void clps711x_clockevent_set_mode(enum clock_event_mode mode, 261static void clps711x_clockevent_set_mode(enum clock_event_mode mode,
255 struct clock_event_device *evt) 262 struct clock_event_device *evt)
256{ 263{
264 disable_irq(IRQ_TC2OI);
265
266 switch (mode) {
267 case CLOCK_EVT_MODE_PERIODIC:
268 enable_irq(IRQ_TC2OI);
269 break;
270 case CLOCK_EVT_MODE_ONESHOT:
271 /* Not supported */
272 case CLOCK_EVT_MODE_SHUTDOWN:
273 case CLOCK_EVT_MODE_UNUSED:
274 case CLOCK_EVT_MODE_RESUME:
275 /* Left event sources disabled, no more interrupts appear */
276 break;
277 }
257} 278}
258 279
259static struct clock_event_device clockevent_clps711x = { 280static struct clock_event_device clockevent_clps711x = {
260 .name = "CLPS711x Clockevents", 281 .name = "clps711x-clockevent",
261 .rating = 300, 282 .rating = 300,
262 .features = CLOCK_EVT_FEAT_PERIODIC, 283 .features = CLOCK_EVT_FEAT_PERIODIC,
263 .set_mode = clps711x_clockevent_set_mode, 284 .set_mode = clps711x_clockevent_set_mode,
@@ -271,8 +292,8 @@ static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id)
271} 292}
272 293
273static struct irqaction clps711x_timer_irq = { 294static struct irqaction clps711x_timer_irq = {
274 .name = "CLPS711x Timer Tick", 295 .name = "clps711x-timer",
275 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 296 .flags = IRQF_TIMER | IRQF_IRQPOLL,
276 .handler = clps711x_timer_interrupt, 297 .handler = clps711x_timer_interrupt,
277}; 298};
278 299
@@ -320,9 +341,9 @@ void __init clps711x_timer_init(void)
320 else 341 else
321 timh = 541440; 342 timh = 541440;
322 } else 343 } else
323 timh = cpu / 144; 344 timh = DIV_ROUND_CLOSEST(cpu, 144);
324 345
325 timl = timh / 256; 346 timl = DIV_ROUND_CLOSEST(timh, 256);
326 347
327 /* All clocks are fixed */ 348 /* All clocks are fixed */
328 add_fixed_clk(clk_pll, "pll", pll); 349 add_fixed_clk(clk_pll, "pll", pll);
@@ -335,13 +356,24 @@ void __init clps711x_timer_init(void)
335 356
336 pr_info("CPU frequency set at %i Hz.\n", cpu); 357 pr_info("CPU frequency set at %i Hz.\n", cpu);
337 358
359 /* Start Timer1 in free running mode (Low frequency) */
360 tmp = clps_readl(SYSCON1) & ~(SYSCON1_TC1S | SYSCON1_TC1M);
361 clps_writel(tmp, SYSCON1);
362
363 setup_sched_clock(clps711x_sched_clock_read, 16, timl);
364
365 clocksource_mmio_init(CLPS711X_VIRT_BASE + TC1D,
366 "clps711x_clocksource", timl, 300, 16,
367 clocksource_mmio_readw_down);
368
369 /* Set Timer2 prescaler */
338 clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D); 370 clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D);
339 371
340 tmp = clps_readl(SYSCON1); 372 /* Start Timer2 in prescale mode (High frequency)*/
341 tmp |= SYSCON1_TC2S | SYSCON1_TC2M; 373 tmp = clps_readl(SYSCON1) | SYSCON1_TC2M | SYSCON1_TC2S;
342 clps_writel(tmp, SYSCON1); 374 clps_writel(tmp, SYSCON1);
343 375
344 clockevents_config_and_register(&clockevent_clps711x, timh, 1, 0xffff); 376 clockevents_config_and_register(&clockevent_clps711x, timh, 0, 0);
345 377
346 setup_irq(IRQ_TC2OI, &clps711x_timer_irq); 378 setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
347} 379}