diff options
Diffstat (limited to 'target/linux/s3c24xx/patches/0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches/0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches/0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch b/target/linux/s3c24xx/patches/0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch new file mode 100755 index 0000000000..f3e35327ec --- /dev/null +++ b/target/linux/s3c24xx/patches/0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch @@ -0,0 +1,128 @@ +From 1da7d81ddc35e3527d10abbc411bc09c81340d70 Mon Sep 17 00:00:00 2001 +From: warmcat <andy@warmcat.com> +Date: Fri, 25 Jul 2008 23:06:00 +0100 +Subject: [PATCH] fix-s3c2410_timer_setup-resume-BUG.patch + +--- + arch/arm/plat-s3c24xx/time.c | 33 +++++++++++++++++++++++++++++++++ + drivers/i2c/chips/pcf50633.c | 9 +++++++-- + 2 files changed, 40 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c +index f8d307b..59e5382 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); + } +diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c +index e23c540..91b9ac3 100644 +--- a/drivers/i2c/chips/pcf50633.c ++++ b/drivers/i2c/chips/pcf50633.c +@@ -1926,9 +1926,11 @@ static int pcf50633_resume(struct device *dev) + struct pcf50633_data *pcf = i2c_get_clientdata(client); + int i; + +- mutex_lock(&pcf->lock); ++ printk(KERN_INFO"a\n"); ++ /* mutex_lock(&pcf->lock); */ /* resume in atomic context */ + + __reg_write(pcf, PCF50633_REG_LEDENA, 0x01); ++ printk(KERN_INFO"b\n"); + + /* Resume all saved registers that don't "survive" standby state */ + __reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m); +@@ -1936,6 +1938,7 @@ static int pcf50633_resume(struct device *dev) + __reg_write(pcf, PCF50633_REG_INT3M, pcf->standby_regs.int3m); + __reg_write(pcf, PCF50633_REG_INT4M, pcf->standby_regs.int4m); + __reg_write(pcf, PCF50633_REG_INT5M, pcf->standby_regs.int5m); ++ printk(KERN_INFO"c\n"); + + __reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2); + __reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout); +@@ -1949,14 +1952,16 @@ static int pcf50633_resume(struct device *dev) + __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout); + __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena); + __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim); ++ printk(KERN_INFO"d\n"); + /* FIXME: one big read? */ + for (i = 0; i < 7; i++) { + u_int8_t reg_out = PCF50633_REG_LDO1OUT + 2*i; + __reg_write(pcf, reg_out, pcf->standby_regs.ldo[i].out); + __reg_write(pcf, reg_out+1, pcf->standby_regs.ldo[i].ena); + } ++ printk(KERN_INFO"e\n"); + +- mutex_unlock(&pcf->lock); ++ /* mutex_unlock(&pcf->lock); */ /* resume in atomic context */ + + pcf50633_irq(pcf->irq, pcf); + +-- +1.5.6.3 + |