diff options
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 76 |
1 files changed, 61 insertions, 15 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 50524436de63..bcbb8d7392be 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -75,10 +75,14 @@ struct omap_dm_timer { | |||
75 | #endif | 75 | #endif |
76 | void __iomem *io_base; | 76 | void __iomem *io_base; |
77 | unsigned reserved:1; | 77 | unsigned reserved:1; |
78 | unsigned enabled:1; | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | #ifdef CONFIG_ARCH_OMAP1 | 81 | #ifdef CONFIG_ARCH_OMAP1 |
81 | 82 | ||
83 | #define omap_dm_clk_enable(x) | ||
84 | #define omap_dm_clk_disable(x) | ||
85 | |||
82 | static struct omap_dm_timer dm_timers[] = { | 86 | static struct omap_dm_timer dm_timers[] = { |
83 | { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, | 87 | { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, |
84 | { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, | 88 | { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, |
@@ -92,6 +96,9 @@ static struct omap_dm_timer dm_timers[] = { | |||
92 | 96 | ||
93 | #elif defined(CONFIG_ARCH_OMAP2) | 97 | #elif defined(CONFIG_ARCH_OMAP2) |
94 | 98 | ||
99 | #define omap_dm_clk_enable(x) clk_enable(x) | ||
100 | #define omap_dm_clk_disable(x) clk_disable(x) | ||
101 | |||
95 | static struct omap_dm_timer dm_timers[] = { | 102 | static struct omap_dm_timer dm_timers[] = { |
96 | { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, | 103 | { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, |
97 | { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, | 104 | { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, |
@@ -154,24 +161,28 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) | |||
154 | { | 161 | { |
155 | u32 l; | 162 | u32 l; |
156 | 163 | ||
157 | if (timer != &dm_timers[0]) { | 164 | if (!cpu_class_is_omap2() || timer != &dm_timers[0]) { |
158 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); | 165 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); |
159 | omap_dm_timer_wait_for_reset(timer); | 166 | omap_dm_timer_wait_for_reset(timer); |
160 | } | 167 | } |
161 | omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK); | 168 | omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); |
162 | 169 | ||
163 | /* Set to smart-idle mode */ | 170 | /* Set to smart-idle mode */ |
164 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); | 171 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); |
165 | l |= 0x02 << 3; | 172 | l |= 0x02 << 3; |
173 | |||
174 | if (cpu_class_is_omap2() && timer == &dm_timers[0]) { | ||
175 | /* Enable wake-up only for GPT1 on OMAP2 CPUs*/ | ||
176 | l |= 1 << 2; | ||
177 | /* Non-posted mode */ | ||
178 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0); | ||
179 | } | ||
166 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); | 180 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); |
167 | } | 181 | } |
168 | 182 | ||
169 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) | 183 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) |
170 | { | 184 | { |
171 | #ifdef CONFIG_ARCH_OMAP2 | 185 | omap_dm_timer_enable(timer); |
172 | clk_enable(timer->iclk); | ||
173 | clk_enable(timer->fclk); | ||
174 | #endif | ||
175 | omap_dm_timer_reset(timer); | 186 | omap_dm_timer_reset(timer); |
176 | } | 187 | } |
177 | 188 | ||
@@ -223,15 +234,36 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) | |||
223 | 234 | ||
224 | void omap_dm_timer_free(struct omap_dm_timer *timer) | 235 | void omap_dm_timer_free(struct omap_dm_timer *timer) |
225 | { | 236 | { |
237 | omap_dm_timer_enable(timer); | ||
226 | omap_dm_timer_reset(timer); | 238 | omap_dm_timer_reset(timer); |
227 | #ifdef CONFIG_ARCH_OMAP2 | 239 | omap_dm_timer_disable(timer); |
228 | clk_disable(timer->iclk); | 240 | |
229 | clk_disable(timer->fclk); | ||
230 | #endif | ||
231 | WARN_ON(!timer->reserved); | 241 | WARN_ON(!timer->reserved); |
232 | timer->reserved = 0; | 242 | timer->reserved = 0; |
233 | } | 243 | } |
234 | 244 | ||
245 | void omap_dm_timer_enable(struct omap_dm_timer *timer) | ||
246 | { | ||
247 | if (timer->enabled) | ||
248 | return; | ||
249 | |||
250 | omap_dm_clk_enable(timer->fclk); | ||
251 | omap_dm_clk_enable(timer->iclk); | ||
252 | |||
253 | timer->enabled = 1; | ||
254 | } | ||
255 | |||
256 | void omap_dm_timer_disable(struct omap_dm_timer *timer) | ||
257 | { | ||
258 | if (!timer->enabled) | ||
259 | return; | ||
260 | |||
261 | omap_dm_clk_disable(timer->iclk); | ||
262 | omap_dm_clk_disable(timer->fclk); | ||
263 | |||
264 | timer->enabled = 0; | ||
265 | } | ||
266 | |||
235 | int omap_dm_timer_get_irq(struct omap_dm_timer *timer) | 267 | int omap_dm_timer_get_irq(struct omap_dm_timer *timer) |
236 | { | 268 | { |
237 | return timer->irq; | 269 | return timer->irq; |
@@ -276,7 +308,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | |||
276 | 308 | ||
277 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) | 309 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) |
278 | { | 310 | { |
279 | return timer->fclk; | 311 | return timer->fclk; |
280 | } | 312 | } |
281 | 313 | ||
282 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | 314 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) |
@@ -406,11 +438,16 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, | |||
406 | unsigned int value) | 438 | unsigned int value) |
407 | { | 439 | { |
408 | omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); | 440 | omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); |
441 | omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); | ||
409 | } | 442 | } |
410 | 443 | ||
411 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) | 444 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) |
412 | { | 445 | { |
413 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); | 446 | unsigned int l; |
447 | |||
448 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); | ||
449 | |||
450 | return l; | ||
414 | } | 451 | } |
415 | 452 | ||
416 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | 453 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) |
@@ -420,12 +457,16 @@ void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | |||
420 | 457 | ||
421 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | 458 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) |
422 | { | 459 | { |
423 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | 460 | unsigned int l; |
461 | |||
462 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | ||
463 | |||
464 | return l; | ||
424 | } | 465 | } |
425 | 466 | ||
426 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) | 467 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) |
427 | { | 468 | { |
428 | return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); | 469 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); |
429 | } | 470 | } |
430 | 471 | ||
431 | int omap_dm_timers_active(void) | 472 | int omap_dm_timers_active(void) |
@@ -436,9 +477,14 @@ int omap_dm_timers_active(void) | |||
436 | struct omap_dm_timer *timer; | 477 | struct omap_dm_timer *timer; |
437 | 478 | ||
438 | timer = &dm_timers[i]; | 479 | timer = &dm_timers[i]; |
480 | |||
481 | if (!timer->enabled) | ||
482 | continue; | ||
483 | |||
439 | if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & | 484 | if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & |
440 | OMAP_TIMER_CTRL_ST) | 485 | OMAP_TIMER_CTRL_ST) { |
441 | return 1; | 486 | return 1; |
487 | } | ||
442 | } | 488 | } |
443 | return 0; | 489 | return 0; |
444 | } | 490 | } |