Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 339920
b: refs/heads/master
c: bfd6d02
h: refs/heads/master
v: v3
  • Loading branch information
Jon Hunter committed Nov 12, 2012
1 parent caf4057 commit 5689996
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 971d0254480572bc6dc5574c28ef8fe014660a31
refs/heads/master: bfd6d021120d5994c4cc94d87ec03642be1540e7
49 changes: 41 additions & 8 deletions trunk/arch/arm/mach-omap2/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,24 @@ void __init omap_dmtimer_init(void)
}
}

/**
* omap_dm_timer_get_errata - get errata flags for a timer
*
* Get the timer errata flags that are specific to the OMAP device being used.
*/
u32 __init omap_dm_timer_get_errata(void)
{
if (cpu_is_omap24xx())
return 0;

return OMAP_TIMER_ERRATA_I103_I767;
}

static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
int gptimer_id,
const char *fck_source,
const char *property)
const char *property,
int posted)
{
char name[10]; /* 10 = sizeof("gptXX_Xck0") */
const char *oh_name;
Expand Down Expand Up @@ -311,10 +325,15 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
}
__omap_dm_timer_init_regs(timer);
__omap_dm_timer_reset(timer, 1, 1);
timer->posted = 1;

timer->rate = clk_get_rate(timer->fclk);
if (posted)
__omap_dm_timer_enable_posted(timer);

/* Check that the intended posted configuration matches the actual */
if (posted != timer->posted)
return -EINVAL;

timer->rate = clk_get_rate(timer->fclk);
timer->reserved = 1;

return res;
Expand All @@ -326,7 +345,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
{
int res;

res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property);
clkev.errata = omap_dm_timer_get_errata();

/*
* For clock-event timers we never read the timer counter and
* so we are not impacted by errata i103 and i767. Therefore,
* we can safely ignore this errata for clock-event timers.
*/
__omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);

res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
OMAP_TIMER_POSTED);
BUG_ON(res);

omap2_gp_timer_irq.dev_id = &clkev;
Expand Down Expand Up @@ -360,7 +389,7 @@ static bool use_gptimer_clksrc;
static cycle_t clocksource_read_cycles(struct clocksource *cs)
{
return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
OMAP_TIMER_POSTED);
OMAP_TIMER_NONPOSTED);
}

static struct clocksource clocksource_gpt = {
Expand All @@ -375,7 +404,7 @@ static u32 notrace dmtimer_read_sched_clock(void)
{
if (clksrc.reserved)
return __omap_dm_timer_read_counter(&clksrc,
OMAP_TIMER_POSTED);
OMAP_TIMER_NONPOSTED);

return 0;
}
Expand Down Expand Up @@ -453,12 +482,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
{
int res;

res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL);
clksrc.errata = omap_dm_timer_get_errata();

res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
OMAP_TIMER_NONPOSTED);
BUG_ON(res);

__omap_dm_timer_load_start(&clksrc,
OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
OMAP_TIMER_POSTED);
OMAP_TIMER_NONPOSTED);
setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);

if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
Expand Down Expand Up @@ -696,6 +728,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
if (timer_dev_attr)
pdata->timer_capability = timer_dev_attr->timer_capability;

pdata->timer_errata = omap_dm_timer_get_errata();
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;

pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/arm/plat-omap/dmtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
}

__omap_dm_timer_reset(timer, 0, 0);
__omap_dm_timer_enable_posted(timer);
omap_dm_timer_disable(timer);
timer->posted = 1;
}

int omap_dm_timer_prepare(struct omap_dm_timer *timer)
Expand Down Expand Up @@ -797,6 +797,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
timer->capability |= OMAP_TIMER_SECURE;
} else {
timer->id = pdev->id;
timer->errata = pdata->timer_errata;
timer->capability = pdata->timer_capability;
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
timer->get_context_loss_count = pdata->get_context_loss_count;
Expand Down
52 changes: 50 additions & 2 deletions trunk/arch/arm/plat-omap/include/plat/dmtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@
#define OMAP_TIMER_NEEDS_RESET 0x10000000
#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000

/*
* timer errata flags
*
* Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
* errata prevents us from using posted mode on these devices, unless the
* timer counter register is never read. For more details please refer to
* the OMAP3/4/5 errata documents.
*/
#define OMAP_TIMER_ERRATA_I103_I767 0x80000000

struct omap_timer_capability_dev_attr {
u32 timer_capability;
};
Expand Down Expand Up @@ -97,6 +107,7 @@ struct timer_regs {
struct dmtimer_platform_data {
/* set_timer_src - Only used for OMAP1 devices */
int (*set_timer_src)(struct platform_device *pdev, int source);
u32 timer_errata;
u32 timer_capability;
int (*get_context_loss_count)(struct device *);
};
Expand Down Expand Up @@ -273,6 +284,7 @@ struct omap_dm_timer {
int ctx_loss_count;
int revision;
u32 capability;
u32 errata;
struct platform_device *pdev;
struct list_head node;
};
Expand Down Expand Up @@ -344,10 +356,46 @@ static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
l |= 1 << 2;

__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
}

/*
* __omap_dm_timer_enable_posted - enables write posted mode
* @timer: pointer to timer instance handle
*
* Enables the write posted mode for the timer. When posted mode is enabled
* writes to certain timer registers are immediately acknowledged by the
* internal bus and hence prevents stalling the CPU waiting for the write to
* complete. Enabling this feature can improve performance for writing to the
* timer registers.
*/
static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
{
if (timer->posted)
return;

if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
return;

/* Match hardware reset default of posted mode */
__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
OMAP_TIMER_CTRL_POSTED, 0);
OMAP_TIMER_CTRL_POSTED, 0);
timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
timer->posted = OMAP_TIMER_POSTED;
}

/**
* __omap_dm_timer_override_errata - override errata flags for a timer
* @timer: pointer to timer handle
* @errata: errata flags to be ignored
*
* For a given timer, override a timer errata by clearing the flags
* specified by the errata argument. A specific erratum should only be
* overridden for a timer if the timer is used in such a way the erratum
* has no impact.
*/
static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
u32 errata)
{
timer->errata &= ~errata;
}

static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
Expand Down

0 comments on commit 5689996

Please sign in to comment.