diff options
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 78 |
1 files changed, 17 insertions, 61 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index dfdc3b2e3201..7c5cb4e128f2 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -170,11 +170,7 @@ static spinlock_t dm_timer_lock; | |||
170 | */ | 170 | */ |
171 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) | 171 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) |
172 | { | 172 | { |
173 | if (timer->posted) | 173 | return __omap_dm_timer_read(timer->io_base, reg, timer->posted); |
174 | while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) | ||
175 | & (reg >> WPSHIFT)) | ||
176 | cpu_relax(); | ||
177 | return readl(timer->io_base + (reg & 0xff)); | ||
178 | } | 174 | } |
179 | 175 | ||
180 | /* | 176 | /* |
@@ -186,11 +182,7 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) | |||
186 | static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, | 182 | static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, |
187 | u32 value) | 183 | u32 value) |
188 | { | 184 | { |
189 | if (timer->posted) | 185 | __omap_dm_timer_write(timer->io_base, reg, value, timer->posted); |
190 | while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) | ||
191 | & (reg >> WPSHIFT)) | ||
192 | cpu_relax(); | ||
193 | writel(value, timer->io_base + (reg & 0xff)); | ||
194 | } | 186 | } |
195 | 187 | ||
196 | static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | 188 | static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) |
@@ -209,7 +201,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | |||
209 | 201 | ||
210 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) | 202 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) |
211 | { | 203 | { |
212 | u32 l; | 204 | int autoidle = 0, wakeup = 0; |
213 | 205 | ||
214 | if (!cpu_class_is_omap2() || timer != &dm_timers[0]) { | 206 | if (!cpu_class_is_omap2() || timer != &dm_timers[0]) { |
215 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); | 207 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); |
@@ -217,28 +209,21 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) | |||
217 | } | 209 | } |
218 | omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); | 210 | omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); |
219 | 211 | ||
220 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); | ||
221 | l |= 0x02 << 3; /* Set to smart-idle mode */ | ||
222 | l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ | ||
223 | |||
224 | /* Enable autoidle on OMAP2 / OMAP3 */ | 212 | /* Enable autoidle on OMAP2 / OMAP3 */ |
225 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) | 213 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) |
226 | l |= 0x1 << 0; | 214 | autoidle = 1; |
227 | 215 | ||
228 | /* | 216 | /* |
229 | * Enable wake-up on OMAP2 CPUs. | 217 | * Enable wake-up on OMAP2 CPUs. |
230 | */ | 218 | */ |
231 | if (cpu_class_is_omap2()) | 219 | if (cpu_class_is_omap2()) |
232 | l |= 1 << 2; | 220 | wakeup = 1; |
233 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); | ||
234 | 221 | ||
235 | /* Match hardware reset default of posted mode */ | 222 | __omap_dm_timer_reset(timer->io_base, autoidle, wakeup); |
236 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, | ||
237 | OMAP_TIMER_CTRL_POSTED); | ||
238 | timer->posted = 1; | 223 | timer->posted = 1; |
239 | } | 224 | } |
240 | 225 | ||
241 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) | 226 | void omap_dm_timer_prepare(struct omap_dm_timer *timer) |
242 | { | 227 | { |
243 | omap_dm_timer_enable(timer); | 228 | omap_dm_timer_enable(timer); |
244 | omap_dm_timer_reset(timer); | 229 | omap_dm_timer_reset(timer); |
@@ -410,25 +395,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start); | |||
410 | 395 | ||
411 | void omap_dm_timer_stop(struct omap_dm_timer *timer) | 396 | void omap_dm_timer_stop(struct omap_dm_timer *timer) |
412 | { | 397 | { |
413 | u32 l; | 398 | unsigned long rate = 0; |
414 | 399 | ||
415 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | ||
416 | if (l & OMAP_TIMER_CTRL_ST) { | ||
417 | l &= ~0x1; | ||
418 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | ||
419 | #ifdef CONFIG_ARCH_OMAP2PLUS | 400 | #ifdef CONFIG_ARCH_OMAP2PLUS |
420 | /* Readback to make sure write has completed */ | 401 | rate = clk_get_rate(timer->fclk); |
421 | omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | ||
422 | /* | ||
423 | * Wait for functional clock period x 3.5 to make sure that | ||
424 | * timer is stopped | ||
425 | */ | ||
426 | udelay(3500000 / clk_get_rate(timer->fclk) + 1); | ||
427 | #endif | 402 | #endif |
428 | } | 403 | |
429 | /* Ack possibly pending interrupt */ | 404 | __omap_dm_timer_stop(timer->io_base, timer->posted, rate); |
430 | omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, | ||
431 | OMAP_TIMER_INT_OVERFLOW); | ||
432 | } | 405 | } |
433 | EXPORT_SYMBOL_GPL(omap_dm_timer_stop); | 406 | EXPORT_SYMBOL_GPL(omap_dm_timer_stop); |
434 | 407 | ||
@@ -451,22 +424,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); | |||
451 | 424 | ||
452 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 425 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) |
453 | { | 426 | { |
454 | int ret = -EINVAL; | ||
455 | |||
456 | if (source < 0 || source >= 3) | 427 | if (source < 0 || source >= 3) |
457 | return -EINVAL; | 428 | return -EINVAL; |
458 | 429 | ||
459 | clk_disable(timer->fclk); | 430 | return __omap_dm_timer_set_source(timer->fclk, |
460 | ret = clk_set_parent(timer->fclk, dm_source_clocks[source]); | 431 | dm_source_clocks[source]); |
461 | clk_enable(timer->fclk); | ||
462 | |||
463 | /* | ||
464 | * When the functional clock disappears, too quick writes seem | ||
465 | * to cause an abort. XXX Is this still necessary? | ||
466 | */ | ||
467 | __delay(300000); | ||
468 | |||
469 | return ret; | ||
470 | } | 432 | } |
471 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); | 433 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); |
472 | 434 | ||
@@ -504,8 +466,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | |||
504 | } | 466 | } |
505 | l |= OMAP_TIMER_CTRL_ST; | 467 | l |= OMAP_TIMER_CTRL_ST; |
506 | 468 | ||
507 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); | 469 | __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted); |
508 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | ||
509 | } | 470 | } |
510 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); | 471 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); |
511 | 472 | ||
@@ -558,8 +519,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); | |||
558 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, | 519 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, |
559 | unsigned int value) | 520 | unsigned int value) |
560 | { | 521 | { |
561 | omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); | 522 | __omap_dm_timer_int_enable(timer->io_base, value); |
562 | omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); | ||
563 | } | 523 | } |
564 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); | 524 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); |
565 | 525 | ||
@@ -575,17 +535,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); | |||
575 | 535 | ||
576 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | 536 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) |
577 | { | 537 | { |
578 | omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); | 538 | __omap_dm_timer_write_status(timer->io_base, value); |
579 | } | 539 | } |
580 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); | 540 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); |
581 | 541 | ||
582 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | 542 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) |
583 | { | 543 | { |
584 | unsigned int l; | 544 | return __omap_dm_timer_read_counter(timer->io_base, timer->posted); |
585 | |||
586 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | ||
587 | |||
588 | return l; | ||
589 | } | 545 | } |
590 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); | 546 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); |
591 | 547 | ||