1 From 6ce7c9b239314f4ee9f86164da8aaf5f78c0d1f1 Mon Sep 17 00:00:00 2001
2 From: warmcat <andy@warmcat.com>
3 Date: Sun, 13 Apr 2008 07:25:49 +0100
4 Subject: [PATCH] fix-s3c2410_timer_setup-resume-BUG.patch
7 arch/arm/plat-s3c24xx/time.c | 33 +++++++++++++++++++++++++++++++++
8 drivers/i2c/chips/pcf50633.c | 9 +++++++--
9 2 files changed, 40 insertions(+), 2 deletions(-)
11 diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
12 index c11d0dd..6989eea 100644
13 --- a/arch/arm/plat-s3c24xx/time.c
14 +++ b/arch/arm/plat-s3c24xx/time.c
17 static unsigned long timer_startval;
18 static unsigned long timer_usec_ticks;
19 +static struct work_struct resume_work;
21 #define TIMER_USEC_SHIFT 16
23 @@ -201,9 +202,12 @@ static void s3c2410_timer_setup (void)
25 pclk = clk_get_rate(clk);
27 + printk("pclk = %d\n", pclk);
29 /* configure clock tick */
31 timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
32 + printk("timer_usec_ticks = %d\n", timer_usec_ticks);
34 tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
35 tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
36 @@ -212,6 +216,11 @@ static void s3c2410_timer_setup (void)
37 tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
39 tcnt = (pclk / 6) / HZ;
41 + /* start the timer running */
42 + tcon |= S3C2410_TCON_T4START | S3C2410_TCON_T4RELOAD;
43 + tcon &= ~S3C2410_TCON_T4MANUALUPD;
44 + __raw_writel(tcon, S3C2410_TCON);
47 /* timers reload after counting zero, so reduce the count by 1 */
48 @@ -247,10 +256,34 @@ static void s3c2410_timer_setup (void)
49 tcon |= S3C2410_TCON_T4START;
50 tcon &= ~S3C2410_TCON_T4MANUALUPD;
51 __raw_writel(tcon, S3C2410_TCON);
53 + __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
58 +static void timer_resume_work(struct work_struct *work)
60 + s3c2410_timer_setup();
63 +/* ooh a nasty situation arises if we try to call s3c2410_timer_setup() from
64 + * the resume handler. It is called in atomic context but the clock APIs
65 + * try to lock a mutex which may sleep. We are in a bit of an unusual
66 + * situation because we don't have a tick source right now, but it should be
67 + * okay to try to schedule a work item... hopefully
70 +static void s3c2410_timer_resume_atomic(void)
72 + int ret = schedule_work(&resume_work);
74 + printk(KERN_INFO"Failed to schedule_work tick ctr (%d)\n", ret);
77 static void __init s3c2410_timer_init (void)
79 + INIT_WORK(&resume_work, timer_resume_work);
80 s3c2410_timer_setup();
81 setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
83 diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
84 index e23c540..91b9ac3 100644
85 --- a/drivers/i2c/chips/pcf50633.c
86 +++ b/drivers/i2c/chips/pcf50633.c
87 @@ -1926,9 +1926,11 @@ static int pcf50633_resume(struct device *dev)
88 struct pcf50633_data *pcf = i2c_get_clientdata(client);
91 - mutex_lock(&pcf->lock);
92 + printk(KERN_INFO"a\n");
93 + /* mutex_lock(&pcf->lock); */ /* resume in atomic context */
95 __reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
96 + printk(KERN_INFO"b\n");
98 /* Resume all saved registers that don't "survive" standby state */
99 __reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m);
100 @@ -1936,6 +1938,7 @@ static int pcf50633_resume(struct device *dev)
101 __reg_write(pcf, PCF50633_REG_INT3M, pcf->standby_regs.int3m);
102 __reg_write(pcf, PCF50633_REG_INT4M, pcf->standby_regs.int4m);
103 __reg_write(pcf, PCF50633_REG_INT5M, pcf->standby_regs.int5m);
104 + printk(KERN_INFO"c\n");
106 __reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2);
107 __reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout);
108 @@ -1949,14 +1952,16 @@ static int pcf50633_resume(struct device *dev)
109 __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
110 __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
111 __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
112 + printk(KERN_INFO"d\n");
113 /* FIXME: one big read? */
114 for (i = 0; i < 7; i++) {
115 u_int8_t reg_out = PCF50633_REG_LDO1OUT + 2*i;
116 __reg_write(pcf, reg_out, pcf->standby_regs.ldo[i].out);
117 __reg_write(pcf, reg_out+1, pcf->standby_regs.ldo[i].ena);
119 + printk(KERN_INFO"e\n");
121 - mutex_unlock(&pcf->lock);
122 + /* mutex_unlock(&pcf->lock); */ /* resume in atomic context */
124 pcf50633_irq(pcf->irq, pcf);