diff options
Diffstat (limited to 'arch/arm/mach-davinci/time.c')
| -rw-r--r-- | arch/arm/mach-davinci/time.c | 90 |
1 files changed, 51 insertions, 39 deletions
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 42d985beece..24ad30f32ae 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -18,12 +18,15 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/platform_device.h> +#include <linux/sched_clock.h> -#include <mach/hardware.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> + #include <mach/cputype.h> +#include <mach/hardware.h> #include <mach/time.h> + #include "clock.h" static struct clock_event_device clockevent_davinci; @@ -178,7 +181,7 @@ static struct timer_s timers[] = { .name = "clockevent", .opts = TIMER_OPTS_DISABLED, .irqaction = { - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = timer_interrupt, } }, @@ -187,7 +190,7 @@ static struct timer_s timers[] = { .period = ~0, .opts = TIMER_OPTS_PERIODIC, .irqaction = { - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = freerun_interrupt, } }, @@ -197,32 +200,36 @@ static void __init timer_init(void) { struct davinci_soc_info *soc_info = &davinci_soc_info; struct davinci_timer_instance *dtip = soc_info->timer_info->timers; + void __iomem *base[2]; int i; /* Global init of each 64-bit timer as a whole */ for(i=0; i<2; i++) { u32 tgcr; - void __iomem *base = dtip[i].base; + + base[i] = ioremap(dtip[i].base, SZ_4K); + if (WARN_ON(!base[i])) + continue; /* Disabled, Internal clock source */ - __raw_writel(0, base + TCR); + __raw_writel(0, base[i] + TCR); /* reset both timers, no pre-scaler for timer34 */ tgcr = 0; - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Set both timers to unchained 32-bit */ tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Unreset timers */ tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Init both counters to zero */ - __raw_writel(0, base + TIM12); - __raw_writel(0, base + TIM34); + __raw_writel(0, base[i] + TIM12); + __raw_writel(0, base[i] + TIM34); } /* Init of each timer as a 32-bit timer */ @@ -231,7 +238,9 @@ static void __init timer_init(void) int timer = ID_TO_TIMER(t->id); u32 irq; - t->base = dtip[timer].base; + t->base = base[timer]; + if (!t->base) + continue; if (IS_TIMER_BOT(t->id)) { t->enamode_shift = 6; @@ -253,8 +262,6 @@ static void __init timer_init(void) irq = USING_COMPARE(t) ? dtip[i].cmp_irq : irq; setup_irq(irq, &t->irqaction); } - - timer32_config(&timers[i]); } } @@ -272,11 +279,18 @@ static struct clocksource clocksource_davinci = { .rating = 300, .read = read_cycles, .mask = CLOCKSOURCE_MASK(32), - .shift = 24, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; /* + * Overwrite weak default sched_clock with something more precise + */ +static u64 notrace davinci_read_sched_clock(void) +{ + return timer32_read(&timers[TID_CLOCKSOURCE]); +} + +/* * clockevent */ static int davinci_set_next_event(unsigned long cycles, @@ -317,13 +331,12 @@ static void davinci_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_davinci = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_next_event = davinci_set_next_event, .set_mode = davinci_set_mode, }; -static void __init davinci_timer_init(void) +void __init davinci_timer_init(void) { struct clk *timer_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; @@ -331,6 +344,7 @@ static void __init davinci_timer_init(void) unsigned int clocksource_id; static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; + int i; clockevent_id = soc_info->timer_info->clockevent_id; clocksource_id = soc_info->timer_info->clocksource_id; @@ -362,52 +376,50 @@ static void __init davinci_timer_init(void) } } - /* init timer hw */ - timer_init(); - timer_clk = clk_get(NULL, "timer0"); BUG_ON(IS_ERR(timer_clk)); - clk_enable(timer_clk); + clk_prepare_enable(timer_clk); + + /* init timer hw */ + timer_init(); davinci_clock_tick_rate = clk_get_rate(timer_clk); /* setup clocksource */ clocksource_davinci.name = id_to_name[clocksource_id]; - clocksource_davinci.mult = - clocksource_khz2mult(davinci_clock_tick_rate/1000, - clocksource_davinci.shift); - if (clocksource_register(&clocksource_davinci)) + if (clocksource_register_hz(&clocksource_davinci, + davinci_clock_tick_rate)) printk(err, clocksource_davinci.name); + sched_clock_register(davinci_read_sched_clock, 32, + davinci_clock_tick_rate); + /* setup clockevent */ clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id]; - clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, - clockevent_davinci.shift); - clockevent_davinci.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_davinci); - clockevent_davinci.min_delta_ns = 50000; /* 50 usec */ clockevent_davinci.cpumask = cpumask_of(0); - clockevents_register_device(&clockevent_davinci); -} - -struct sys_timer davinci_timer = { - .init = davinci_timer_init, -}; + clockevents_config_and_register(&clockevent_davinci, + davinci_clock_tick_rate, 1, 0xfffffffe); + for (i=0; i< ARRAY_SIZE(timers); i++) + timer32_config(&timers[i]); +} /* reset board using watchdog timer */ -void davinci_watchdog_reset(void) +void davinci_watchdog_reset(struct platform_device *pdev) { u32 tgcr, wdtcr; - struct platform_device *pdev = &davinci_wdt_device; - void __iomem *base = IO_ADDRESS(pdev->resource[0].start); + void __iomem *base; struct clk *wd_clk; + base = ioremap(pdev->resource[0].start, SZ_4K); + if (WARN_ON(!base)) + return; + wd_clk = clk_get(&pdev->dev, NULL); if (WARN_ON(IS_ERR(wd_clk))) return; - clk_enable(wd_clk); + clk_prepare_enable(wd_clk); /* disable, internal clock source */ __raw_writel(0, base + TCR); |
