Commit 2a5d6f35 authored by Timo Teras's avatar Timo Teras Committed by Juha Yrjola

ARM: OMAP: Update dmtimers

- Initialize timer outside of spinlock to reduce the time the spinlock is held
- Do clk_get to the source clocks during initialization to avoid sleeping later
- New function to set counter register
Signed-off-by: default avatarTimo Teras <timo.teras@solidboot.com>
Signed-off-by: default avatarJuha Yrjola <juha.yrjola@solidboot.com>
parent fca591f6
...@@ -107,6 +107,14 @@ static struct omap_dm_timer dm_timers[] = { ...@@ -107,6 +107,14 @@ static struct omap_dm_timer dm_timers[] = {
{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 }, { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
}; };
static const char *dm_source_names[] = {
"sys_ck",
"func_32k_ck",
"alt_ck"
};
static struct clk *dm_source_clocks[3];
#else #else
#error OMAP architecture not supported! #error OMAP architecture not supported!
...@@ -114,7 +122,6 @@ static struct omap_dm_timer dm_timers[] = { ...@@ -114,7 +122,6 @@ static struct omap_dm_timer dm_timers[] = {
#endif #endif
static const int dm_timer_count = ARRAY_SIZE(dm_timers); static const int dm_timer_count = ARRAY_SIZE(dm_timers);
static spinlock_t dm_timer_lock; static spinlock_t dm_timer_lock;
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
...@@ -159,9 +166,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) ...@@ -159,9 +166,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
} }
static void omap_dm_timer_reserve(struct omap_dm_timer *timer) static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
{ {
timer->reserved = 1;
#ifdef CONFIG_ARCH_OMAP2 #ifdef CONFIG_ARCH_OMAP2
clk_enable(timer->iclk); clk_enable(timer->iclk);
clk_enable(timer->fclk); clk_enable(timer->fclk);
...@@ -181,11 +187,14 @@ struct omap_dm_timer *omap_dm_timer_request(void) ...@@ -181,11 +187,14 @@ struct omap_dm_timer *omap_dm_timer_request(void)
continue; continue;
timer = &dm_timers[i]; timer = &dm_timers[i];
omap_dm_timer_reserve(timer); timer->reserved = 1;
break; break;
} }
spin_unlock_irqrestore(&dm_timer_lock, flags); spin_unlock_irqrestore(&dm_timer_lock, flags);
if (timer != NULL)
omap_dm_timer_prepare(timer);
return timer; return timer;
} }
...@@ -204,9 +213,11 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) ...@@ -204,9 +213,11 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
} }
timer = &dm_timers[id-1]; timer = &dm_timers[id-1];
omap_dm_timer_reserve(timer); timer->reserved = 1;
spin_unlock_irqrestore(&dm_timer_lock, flags); spin_unlock_irqrestore(&dm_timer_lock, flags);
omap_dm_timer_prepare(timer);
return timer; return timer;
} }
...@@ -318,21 +329,12 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) ...@@ -318,21 +329,12 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{ {
static const char *source_timers[] = {
"sys_ck",
"func_32k_ck",
"alt_ck"
};
struct clk *parent;
if (source < 0 || source >= 3) if (source < 0 || source >= 3)
return; return;
parent = clk_get(NULL, source_timers[source]);
clk_disable(timer->fclk); clk_disable(timer->fclk);
clk_set_parent(timer->fclk, parent); clk_set_parent(timer->fclk, dm_source_clocks[source]);
clk_enable(timer->fclk); clk_enable(timer->fclk);
clk_put(parent);
/* When the functional clock disappears, too quick writes seem to /* When the functional clock disappears, too quick writes seem to
* cause an abort. */ * cause an abort. */
...@@ -421,6 +423,11 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) ...@@ -421,6 +423,11 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
} }
void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
{
return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
}
int omap_dm_timers_active(void) int omap_dm_timers_active(void)
{ {
int i; int i;
...@@ -445,6 +452,13 @@ int omap_dm_timer_init(void) ...@@ -445,6 +452,13 @@ int omap_dm_timer_init(void)
return -ENODEV; return -ENODEV;
spin_lock_init(&dm_timer_lock); spin_lock_init(&dm_timer_lock);
#ifdef CONFIG_ARCH_OMAP2
for (i = 0; i < ARRAY_SIZE(dm_source_names); i++) {
dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
BUG_ON(dm_source_clocks[i] == NULL);
}
#endif
for (i = 0; i < dm_timer_count; i++) { for (i = 0; i < dm_timer_count; i++) {
#ifdef CONFIG_ARCH_OMAP2 #ifdef CONFIG_ARCH_OMAP2
char clk_name[16]; char clk_name[16];
......
...@@ -73,6 +73,7 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int valu ...@@ -73,6 +73,7 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int valu
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
int omap_dm_timers_active(void); int omap_dm_timers_active(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment