/* * This must be globally accessible by davinci_timer_read_sched_clock(), so * let's keep it here.
*/ staticstruct { struct clocksource dev; void __iomem *base; unsignedint tim_off;
} davinci_clocksource;
tcr = DAVINCI_TIMER_ENAMODE_DISABLED <<
DAVINCI_TIMER_ENAMODE_SHIFT_TIM12; /* * This function is only ever called if we're using both timer * halves. In this case TIM34 runs in periodic mode and we must * not modify it.
*/
tcr |= DAVINCI_TIMER_ENAMODE_PERIODIC <<
DAVINCI_TIMER_ENAMODE_SHIFT_TIM34;
writel_relaxed(tcr, base + DAVINCI_TIMER_REG_TCR);
}
/* * Standard use-case: we're using tim12 for clockevent and tim34 for * clocksource. The default is making the former run in oneshot mode * and the latter in periodic mode.
*/ staticvoid davinci_clocksource_init_tim34(void __iomem *base)
{ int tcr;
writel_relaxed(0x0, base + DAVINCI_TIMER_REG_TIM34);
writel_relaxed(UINT_MAX, base + DAVINCI_TIMER_REG_PRD34);
writel_relaxed(tcr, base + DAVINCI_TIMER_REG_TCR);
}
/* * Special use-case on da830: the DSP may use tim34. We're using tim12 for * both clocksource and clockevent. We set tim12 to periodic and don't touch * tim34.
*/ staticvoid davinci_clocksource_init_tim12(void __iomem *base)
{ unsignedint tcr;
writel_relaxed(0x0, base + DAVINCI_TIMER_REG_TIM12);
writel_relaxed(UINT_MAX, base + DAVINCI_TIMER_REG_PRD12);
writel_relaxed(tcr, base + DAVINCI_TIMER_REG_TCR);
}
staticvoid davinci_timer_init(void __iomem *base)
{ /* Set clock to internal mode and disable it. */
writel_relaxed(0x0, base + DAVINCI_TIMER_REG_TCR); /* * Reset both 32-bit timers, set no prescaler for timer 34, set the * timer to dual 32-bit unchained mode, unreset both 32-bit timers.
*/
writel_relaxed(DAVINCI_TIMER_TGCR_DEFAULT,
base + DAVINCI_TIMER_REG_TGCR); /* Init both counters to zero. */
writel_relaxed(0x0, base + DAVINCI_TIMER_REG_TIM12);
writel_relaxed(0x0, base + DAVINCI_TIMER_REG_TIM34);
}
int __init davinci_timer_register(struct clk *clk, conststruct davinci_timer_cfg *timer_cfg)
{ struct davinci_clockevent *clockevent; unsignedint tick_rate; void __iomem *base; int rv;
rv = clk_prepare_enable(clk); if (rv) {
pr_err("Unable to prepare and enable the timer clock\n"); return rv;
}
if (!request_mem_region(timer_cfg->reg.start,
resource_size(&timer_cfg->reg), "davinci-timer")) {
pr_err("Unable to request memory region\n");
rv = -EBUSY; goto exit_clk_disable;
}
base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg)); if (!base) {
pr_err("Unable to map the register range\n");
rv = -ENOMEM; goto exit_mem_region;
}
rv = of_address_to_resource(np, 0, &timer_cfg.reg); if (rv) {
pr_err("Unable to get the register range for timer\n"); return rv;
}
rv = of_irq_to_resource_table(np, timer_cfg.irq,
DAVINCI_TIMER_NUM_IRQS); if (rv != DAVINCI_TIMER_NUM_IRQS) {
pr_err("Unable to get the interrupts for timer\n"); return rv;
}
clk = of_clk_get(np, 0); if (IS_ERR(clk)) {
pr_err("Unable to get the timer clock\n"); return PTR_ERR(clk);
}
rv = davinci_timer_register(clk, &timer_cfg); if (rv)
clk_put(clk);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.