disable IMQ on 2.6.28 as well -- people should use IFB..
[openwrt.git] / target / linux / s3c24xx / patches / 0080-fix-s3c2410_timer_setup-resume-BUG.patch.patch
1 From 1da7d81ddc35e3527d10abbc411bc09c81340d70 Mon Sep 17 00:00:00 2001
2 From: warmcat <andy@warmcat.com>
3 Date: Fri, 25 Jul 2008 23:06:00 +0100
4 Subject: [PATCH] fix-s3c2410_timer_setup-resume-BUG.patch
5
6 ---
7  arch/arm/plat-s3c24xx/time.c |   33 +++++++++++++++++++++++++++++++++
8  drivers/i2c/chips/pcf50633.c |    9 +++++++--
9  2 files changed, 40 insertions(+), 2 deletions(-)
10
11 diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
12 index f8d307b..59e5382 100644
13 --- a/arch/arm/plat-s3c24xx/time.c
14 +++ b/arch/arm/plat-s3c24xx/time.c
15 @@ -42,6 +42,7 @@
16  
17  static unsigned long timer_startval;
18  static unsigned long timer_usec_ticks;
19 +static struct work_struct resume_work;
20  
21  #define TIMER_USEC_SHIFT 16
22  
23 @@ -199,9 +200,12 @@ static void s3c2410_timer_setup (void)
24  
25                 pclk = clk_get_rate(clk);
26  
27 +               printk("pclk = %d\n", pclk);
28 +
29                 /* configure clock tick */
30  
31                 timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
32 +               printk("timer_usec_ticks = %d\n", timer_usec_ticks);
33  
34                 tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
35                 tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
36 @@ -210,6 +214,11 @@ static void s3c2410_timer_setup (void)
37                 tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
38  
39                 tcnt = (pclk / 6) / HZ;
40 +
41 +               /* start the timer running */
42 +               tcon |= S3C2410_TCON_T4START | S3C2410_TCON_T4RELOAD;
43 +               tcon &= ~S3C2410_TCON_T4MANUALUPD;
44 +               __raw_writel(tcon, S3C2410_TCON);
45         }
46  
47         /* timers reload after counting zero, so reduce the count by 1 */
48 @@ -245,10 +254,34 @@ static void s3c2410_timer_setup (void)
49         tcon |= S3C2410_TCON_T4START;
50         tcon &= ~S3C2410_TCON_T4MANUALUPD;
51         __raw_writel(tcon, S3C2410_TCON);
52 +
53 +       __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
54 +                    S3C2410_INTMSK);
55 +
56 +}
57 +
58 +static void timer_resume_work(struct work_struct *work)
59 +{
60 +       s3c2410_timer_setup();
61 +}
62 +
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
68 + */
69 +
70 +static void s3c2410_timer_resume_atomic(void)
71 +{
72 +       int ret = schedule_work(&resume_work);
73 +       if (!ret)
74 +               printk(KERN_INFO"Failed to schedule_work tick ctr (%d)\n", ret);
75  }
76  
77  static void __init s3c2410_timer_init (void)
78  {
79 +       INIT_WORK(&resume_work, timer_resume_work);
80         s3c2410_timer_setup();
81         setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
82  }
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);
89         int i;
90  
91 -       mutex_lock(&pcf->lock);
92 +       printk(KERN_INFO"a\n");
93 +       /* mutex_lock(&pcf->lock); */  /* resume in atomic context */
94  
95         __reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
96 +       printk(KERN_INFO"b\n");
97  
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");
105  
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);
118         }
119 +       printk(KERN_INFO"e\n");
120  
121 -       mutex_unlock(&pcf->lock);
122 +       /* mutex_unlock(&pcf->lock); */ /* resume in atomic context */
123  
124         pcf50633_irq(pcf->irq, pcf);
125  
126 -- 
127 1.5.6.3
128