From 54e9d11cebb37fafb4928273bd5fd4ee7cd49f55 Mon Sep 17 00:00:00 2001 From: warmcat Date: Wed, 19 Nov 2008 17:09:33 +0000 Subject: 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 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); } diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c index e23c540d15d..91b9ac332e1 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); -- cgit v1.2.3