diff options
author | warmcat <andy@warmcat.com> | 2008-11-19 17:09:33 +0000 |
---|---|---|
committer | Andy Green <agreen@pads.home.warmcat.com> | 2008-11-19 17:09:33 +0000 |
commit | 54e9d11cebb37fafb4928273bd5fd4ee7cd49f55 (patch) | |
tree | d65b221fcce666ea68d799332c66d40378418cc8 /arch/arm/plat-s3c24xx/time.c | |
parent | 1b608a5f6d7cc60c64f654d27b8557a8a69997c9 (diff) |
fix-s3c2410_timer_setup-resume-BUG.patch
Diffstat (limited to 'arch/arm/plat-s3c24xx/time.c')
-rw-r--r-- | arch/arm/plat-s3c24xx/time.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c index 9c66fcd4099..410937f8c4b 100644 --- a/arch/arm/plat-s3c24xx/time.c +++ b/arch/arm/plat-s3c24xx/time.c @@ -42,6 +42,7 @@ static unsigned long timer_startval; static unsigned long timer_usec_ticks; +static struct work_struct resume_work; #define TIMER_USEC_SHIFT 16 @@ -199,9 +200,12 @@ static void s3c2410_timer_setup (void) pclk = clk_get_rate(clk); + printk("pclk = %d\n", pclk); + /* configure clock tick */ timer_usec_ticks = timer_mask_usec_ticks(6, pclk); + printk("timer_usec_ticks = %d\n", timer_usec_ticks); tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; @@ -210,6 +214,11 @@ static void s3c2410_timer_setup (void) tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; tcnt = (pclk / 6) / HZ; + + /* start the timer running */ + tcon |= S3C2410_TCON_T4START | S3C2410_TCON_T4RELOAD; + tcon &= ~S3C2410_TCON_T4MANUALUPD; + __raw_writel(tcon, S3C2410_TCON); } /* timers reload after counting zero, so reduce the count by 1 */ @@ -245,10 +254,34 @@ static void s3c2410_timer_setup (void) tcon |= S3C2410_TCON_T4START; tcon &= ~S3C2410_TCON_T4MANUALUPD; __raw_writel(tcon, S3C2410_TCON); + + __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)), + S3C2410_INTMSK); + +} + +static void timer_resume_work(struct work_struct *work) +{ + s3c2410_timer_setup(); +} + +/* ooh a nasty situation arises if we try to call s3c2410_timer_setup() from + * the resume handler. It is called in atomic context but the clock APIs + * try to lock a mutex which may sleep. We are in a bit of an unusual + * situation because we don't have a tick source right now, but it should be + * okay to try to schedule a work item... hopefully + */ + +static void s3c2410_timer_resume_atomic(void) +{ + int ret = schedule_work(&resume_work); + if (!ret) + printk(KERN_INFO"Failed to schedule_work tick ctr (%d)\n", ret); } static void __init s3c2410_timer_init (void) { + INIT_WORK(&resume_work, timer_resume_work); s3c2410_timer_setup(); setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); } |