From: Timo Teras Date: Mon, 25 Sep 2006 09:41:35 +0000 (+0300) Subject: ARM: OMAP: Use GPT iclk only when needed X-Git-Tag: v2.6.19-rc1~885^2~18^2~18 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=fa4bb626c660ada7cad3cc7e45da14f8ec17847c;p=linux-2.6-omap-h63xx.git 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 Signed-off-by: Juha Yrjola Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 50524436de6..fb2a23e7c17 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -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; }