Skip to content

Commit

Permalink
ARM: OMAP: Add support for dmtimer v2 ip
Browse files Browse the repository at this point in the history
The registers are slightly different between v1 and v2 ip that
is available in omap4 and later for some timers.

Add support for v2 ip by mapping the interrupt related registers
separately and adding func_base for the functional registers.

Also disable dmtimer driver features on omap4 for now as
those need the hwmod conversion series to deal with enabling
the timers properly in omap_dm_timer_init.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
Tested-by: Hemant Pedanekar <hemantp@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
  • Loading branch information
Tony Lindgren committed Sep 19, 2011
1 parent ceb1c53 commit ee17f11
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 76 deletions.
23 changes: 12 additions & 11 deletions arch/arm/mach-omap2/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_gpt;

__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
__omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);

evt->event_handler(evt);
return IRQ_HANDLED;
Expand All @@ -93,7 +93,7 @@ static struct irqaction omap2_gp_timer_irq = {
static int omap2_gp_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
0xffffffff - cycles, 1);

return 0;
Expand All @@ -104,16 +104,16 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
{
u32 period;

__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
__omap_dm_timer_stop(&clkev, 1, clkev.rate);

switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
period = clkev.rate / HZ;
period -= 1;
/* Looks like we need to first set the load value separately */
__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
0xffffffff - period, 1);
__omap_dm_timer_load_start(clkev.io_base,
__omap_dm_timer_load_start(&clkev,
OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
0xffffffff - period, 1);
break;
Expand Down Expand Up @@ -189,7 +189,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
clk_put(src);
}
}
__omap_dm_timer_reset(timer->io_base, 1, 1);
__omap_dm_timer_init_regs(timer);
__omap_dm_timer_reset(timer, 1, 1);
timer->posted = 1;

timer->rate = clk_get_rate(timer->fclk);
Expand All @@ -210,7 +211,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
omap2_gp_timer_irq.dev_id = (void *)&clkev;
setup_irq(clkev.irq, &omap2_gp_timer_irq);

__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);

clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
clockevent_gpt.shift);
Expand Down Expand Up @@ -251,7 +252,7 @@ static struct omap_dm_timer clksrc;
static DEFINE_CLOCK_DATA(cd);
static cycle_t clocksource_read_cycles(struct clocksource *cs)
{
return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
}

static struct clocksource clocksource_gpt = {
Expand All @@ -266,7 +267,7 @@ static void notrace dmtimer_update_sched_clock(void)
{
u32 cyc;

cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
cyc = __omap_dm_timer_read_counter(&clksrc, 1);

update_sched_clock(&cd, cyc, (u32)~0);
}
Expand All @@ -276,7 +277,7 @@ unsigned long long notrace sched_clock(void)
u32 cyc = 0;

if (clksrc.reserved)
cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
cyc = __omap_dm_timer_read_counter(&clksrc, 1);

return cyc_to_sched_clock(&cd, cyc, (u32)~0);
}
Expand All @@ -293,7 +294,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
gptimer_id, clksrc.rate);

__omap_dm_timer_load_start(clksrc.io_base,
__omap_dm_timer_load_start(&clksrc,
OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);

Expand Down
32 changes: 22 additions & 10 deletions arch/arm/plat-omap/dmtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ static spinlock_t dm_timer_lock;
*/
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
{
return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
return __omap_dm_timer_read(timer, reg, timer->posted);
}

/*
Expand All @@ -182,15 +183,19 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
u32 value)
{
__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
__omap_dm_timer_write(timer, reg, value, timer->posted);
}

static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
{
int c;

if (!timer->sys_stat)
return;

c = 0;
while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
while (!(__raw_readl(timer->sys_stat) & 1)) {
c++;
if (c > 100000) {
printk(KERN_ERR "Timer failed to reset\n");
Expand Down Expand Up @@ -219,7 +224,7 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
if (cpu_class_is_omap2())
wakeup = 1;

__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
__omap_dm_timer_reset(timer, autoidle, wakeup);
timer->posted = 1;
}

Expand Down Expand Up @@ -401,7 +406,7 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
rate = clk_get_rate(timer->fclk);
#endif

__omap_dm_timer_stop(timer->io_base, timer->posted, rate);
__omap_dm_timer_stop(timer, timer->posted, rate);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);

Expand Down Expand Up @@ -466,7 +471,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
}
l |= OMAP_TIMER_CTRL_ST;

__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
__omap_dm_timer_load_start(timer, l, load, timer->posted);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);

Expand Down Expand Up @@ -519,29 +524,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
__omap_dm_timer_int_enable(timer->io_base, value);
__omap_dm_timer_int_enable(timer, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);

unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
unsigned int l;

l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
l = __raw_readl(timer->irq_stat);

return l;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);

void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
__omap_dm_timer_write_status(timer->io_base, value);
__omap_dm_timer_write_status(timer, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);

unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
return __omap_dm_timer_read_counter(timer, timer->posted);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);

Expand Down Expand Up @@ -601,6 +606,9 @@ static int __init omap_dm_timer_init(void)
dm_timer_count = omap4_dm_timer_count;
dm_source_names = omap4_dm_source_names;
dm_source_clocks = omap4_dm_source_clocks;

pr_err("dmtimers disabled for omap4 until hwmod conversion\n");
return -ENODEV;
}

if (cpu_class_is_omap2())
Expand Down Expand Up @@ -630,8 +638,12 @@ static int __init omap_dm_timer_init(void)
if (sys_timer_reserved & (1 << i)) {
timer->reserved = 1;
timer->posted = 1;
continue;
}
#endif
omap_dm_timer_enable(timer);
__omap_dm_timer_init_regs(timer);
omap_dm_timer_disable(timer);
}

return 0;
Expand Down
Loading

0 comments on commit ee17f11

Please sign in to comment.