ARM: OMAP: Use GPT iclk only when needed

This patch makes the OMAP2 dmtimers module using the interface
clocks only while the registers are accessed (except GPT1 which has
iclk enabled all the time).

Signed-off-by: Timo Teras <timo.teras@solidboot.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
Timo Teras 2006-09-25 12:41:35 +03:00 committed by Tony Lindgren
parent 123e9a5573
commit fa4bb626c6
1 changed files with 62 additions and 13 deletions

View File

@ -79,6 +79,9 @@ struct omap_dm_timer {
#ifdef CONFIG_ARCH_OMAP1
#define omap_dm_clk_enable(x)
#define omap_dm_clk_disable(x)
static struct omap_dm_timer dm_timers[] = {
{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
@ -92,6 +95,9 @@ static struct omap_dm_timer dm_timers[] = {
#elif defined(CONFIG_ARCH_OMAP2)
#define omap_dm_clk_enable(x) clk_enable(x)
#define omap_dm_clk_disable(x) clk_disable(x)
static struct omap_dm_timer dm_timers[] = {
{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
@ -168,11 +174,15 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
{
#ifdef CONFIG_ARCH_OMAP2
clk_enable(timer->iclk);
clk_enable(timer->fclk);
#endif
omap_dm_clk_enable(timer->fclk);
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_reset(timer);
/* Leave iclk enabled for GPT1 as it is needed for the
* system timer to work properly. */
if (timer != &dm_timers[0])
omap_dm_clk_disable(timer->iclk);
}
struct omap_dm_timer *omap_dm_timer_request(void)
@ -223,11 +233,14 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
void omap_dm_timer_free(struct omap_dm_timer *timer)
{
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_reset(timer);
#ifdef CONFIG_ARCH_OMAP2
clk_disable(timer->iclk);
clk_disable(timer->fclk);
#endif
omap_dm_clk_disable(timer->iclk);
if (timer == &dm_timers[0])
omap_dm_clk_disable(timer->iclk);
omap_dm_clk_disable(timer->fclk);
WARN_ON(!timer->reserved);
timer->reserved = 0;
}
@ -276,7 +289,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
{
return timer->fclk;
return timer->fclk;
}
__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
@ -288,29 +301,35 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
void omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
omap_dm_clk_disable(timer->iclk);
}
void omap_dm_timer_start(struct omap_dm_timer *timer)
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (!(l & OMAP_TIMER_CTRL_ST)) {
l |= OMAP_TIMER_CTRL_ST;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
omap_dm_clk_disable(timer->iclk);
}
void omap_dm_timer_stop(struct omap_dm_timer *timer)
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (l & OMAP_TIMER_CTRL_ST) {
l &= ~0x1;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
omap_dm_clk_disable(timer->iclk);
}
#ifdef CONFIG_ARCH_OMAP1
@ -348,6 +367,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
@ -356,6 +376,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
omap_dm_clk_disable(timer->iclk);
}
void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
@ -363,6 +384,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (enable)
l |= OMAP_TIMER_CTRL_CE;
@ -370,6 +392,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
l &= ~OMAP_TIMER_CTRL_CE;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
omap_dm_clk_disable(timer->iclk);
}
@ -378,6 +401,7 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
OMAP_TIMER_CTRL_PT | (0x03 << 10));
@ -387,12 +411,14 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
l |= OMAP_TIMER_CTRL_PT;
l |= trigger << 10;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_clk_disable(timer->iclk);
}
void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
{
u32 l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
if (prescaler >= 0x00 && prescaler <= 0x07) {
@ -400,32 +426,51 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
l |= prescaler << 2;
}
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_clk_disable(timer->iclk);
}
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
omap_dm_clk_disable(timer->iclk);
}
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
unsigned int l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
omap_dm_clk_disable(timer->iclk);
return l;
}
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
omap_dm_clk_disable(timer->iclk);
}
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
unsigned int l;
omap_dm_clk_enable(timer->iclk);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
omap_dm_clk_disable(timer->iclk);
return l;
}
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);
omap_dm_clk_enable(timer->iclk);
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
omap_dm_clk_disable(timer->iclk);
}
int omap_dm_timers_active(void)
@ -436,9 +481,13 @@ int omap_dm_timers_active(void)
struct omap_dm_timer *timer;
timer = &dm_timers[i];
omap_dm_clk_enable(timer->iclk);
if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
OMAP_TIMER_CTRL_ST)
OMAP_TIMER_CTRL_ST) {
omap_dm_clk_disable(timer->iclk);
return 1;
}
omap_dm_clk_disable(timer->iclk);
}
return 0;
}