1 From d3063c1ec65b37b45e808313133196185ea4901f Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 4 Apr 2008 11:30:03 +0100
4 Subject: [PATCH] fix-i2c-s3c2410-resume-race.patch
5 fix-i2c-s3c2410-resume-race.patch
7 There is a nasty race between i2c-s3c2410 resume and resume of I2C
8 driver and the client drivers -- the watchdog device actually gets to
9 use the dead I2C bus before it is reinitialized by the I2C driver
10 resume! This patch makes sure any customers get turned away until
11 the shopkeeper has woken up.
13 Signed-off-by: Andy Green <andy@openmoko.com>
15 drivers/i2c/busses/i2c-s3c2410.c | 35 ++++++++++++++++++++++++++++++++++-
16 1 files changed, 34 insertions(+), 1 deletions(-)
18 diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
19 index c44ada5..5ac8309 100644
20 --- a/drivers/i2c/busses/i2c-s3c2410.c
21 +++ b/drivers/i2c/busses/i2c-s3c2410.c
22 @@ -71,6 +71,8 @@ struct s3c24xx_i2c {
24 struct resource *ioarea;
25 struct i2c_adapter adap;
30 /* default platform data to use if not supplied in the platform_device
31 @@ -156,6 +158,14 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
34 tmp = readl(i2c->regs + S3C2410_IICCON);
38 + * If the IICCON[5]=0, IICCON[4] does not operate correctly.
39 + * So, It is recommended that you should set IICCON[5]=1,
40 + * although you does not use the IIC interrupt.
43 writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
46 @@ -282,7 +292,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
49 dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
50 - s3c24xx_i2c_disable_irq(i2c);
51 + s3c24xx_i2c_disable_irq(i2c);
55 @@ -502,6 +512,14 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
56 unsigned long timeout;
59 + if (i2c->suspended) {
61 + "Hey I am still asleep (suspended: %d), retry later\n",
67 ret = s3c24xx_i2c_set_master(i2c);
69 dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
70 @@ -886,6 +904,17 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
75 +static int s3c24xx_i2c_suspend(struct platform_device *dev, pm_message_t state)
77 + struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
85 static int s3c24xx_i2c_resume(struct platform_device *dev)
87 struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
88 @@ -893,6 +922,8 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
90 s3c24xx_i2c_init(i2c);
97 @@ -905,6 +936,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
98 static struct platform_driver s3c2410_i2c_driver = {
99 .probe = s3c24xx_i2c_probe,
100 .remove = s3c24xx_i2c_remove,
101 + .suspend = s3c24xx_i2c_suspend,
102 .resume = s3c24xx_i2c_resume,
104 .owner = THIS_MODULE,
105 @@ -915,6 +947,7 @@ static struct platform_driver s3c2410_i2c_driver = {
106 static struct platform_driver s3c2440_i2c_driver = {
107 .probe = s3c24xx_i2c_probe,
108 .remove = s3c24xx_i2c_remove,
109 + .suspend = s3c24xx_i2c_suspend,
110 .resume = s3c24xx_i2c_resume,
112 .owner = THIS_MODULE,