changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1006-fix-i2c-s3c2410-resume-race.patch.patch
diff --git a/target/linux/s3c24xx/patches-2.6.24/1006-fix-i2c-s3c2410-resume-race.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1006-fix-i2c-s3c2410-resume-race.patch.patch
new file mode 100644 (file)
index 0000000..720608e
--- /dev/null
@@ -0,0 +1,115 @@
+From d3063c1ec65b37b45e808313133196185ea4901f Mon Sep 17 00:00:00 2001
+From: mokopatches <mokopatches@openmoko.org>
+Date: Fri, 4 Apr 2008 11:30:03 +0100
+Subject: [PATCH] fix-i2c-s3c2410-resume-race.patch
+ fix-i2c-s3c2410-resume-race.patch
+
+There is a nasty race between i2c-s3c2410 resume and resume of I2C
+driver and the client drivers -- the watchdog device actually gets to
+use the dead I2C bus before it is reinitialized by the I2C driver
+resume!  This patch makes sure any customers get turned away until
+the shopkeeper has woken up.
+
+Signed-off-by: Andy Green <andy@openmoko.com>
+---
+ drivers/i2c/busses/i2c-s3c2410.c |   35 ++++++++++++++++++++++++++++++++++-
+ 1 files changed, 34 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
+index c44ada5..5ac8309 100644
+--- a/drivers/i2c/busses/i2c-s3c2410.c
++++ b/drivers/i2c/busses/i2c-s3c2410.c
+@@ -71,6 +71,8 @@ struct s3c24xx_i2c {
+       struct resource         *irq;
+       struct resource         *ioarea;
+       struct i2c_adapter      adap;
++
++      int                     suspended;
+ };
+ /* default platform data to use if not supplied in the platform_device
+@@ -156,6 +158,14 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
+       unsigned long tmp;
+       
+       tmp = readl(i2c->regs + S3C2410_IICCON);
++
++/* S3c2442 datasheet
++ *
++ * If the IICCON[5]=0, IICCON[4] does not operate correctly.
++ * So, It is recommended that you should set IICCON[5]=1,
++ * although you does not use the IIC interrupt.
++ */
++
+       writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
+ }
+@@ -282,7 +292,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
+       case STATE_STOP:
+               dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
+-              s3c24xx_i2c_disable_irq(i2c);           
++              s3c24xx_i2c_disable_irq(i2c);
+               goto out_ack;
+       case STATE_START:
+@@ -502,6 +512,14 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
+       unsigned long timeout;
+       int ret;
++      if (i2c->suspended) {
++              dev_err(i2c->dev,
++                  "Hey I am still asleep (suspended: %d), retry later\n",
++                  i2c->suspended);
++              ret = -EAGAIN;
++              goto out;
++      }
++
+       ret = s3c24xx_i2c_set_master(i2c);
+       if (ret != 0) {
+               dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
+@@ -886,6 +904,17 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
+ }
+ #ifdef CONFIG_PM
++
++static int s3c24xx_i2c_suspend(struct platform_device *dev, pm_message_t state)
++{
++      struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
++
++      if (i2c != NULL)
++              i2c->suspended++;
++
++      return 0;
++}
++
+ static int s3c24xx_i2c_resume(struct platform_device *dev)
+ {
+       struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+@@ -893,6 +922,8 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
+       if (i2c != NULL)
+               s3c24xx_i2c_init(i2c);
++      i2c->suspended--;
++
+       return 0;
+ }
+@@ -905,6 +936,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
+ static struct platform_driver s3c2410_i2c_driver = {
+       .probe          = s3c24xx_i2c_probe,
+       .remove         = s3c24xx_i2c_remove,
++      .suspend        = s3c24xx_i2c_suspend,
+       .resume         = s3c24xx_i2c_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+@@ -915,6 +947,7 @@ static struct platform_driver s3c2410_i2c_driver = {
+ static struct platform_driver s3c2440_i2c_driver = {
+       .probe          = s3c24xx_i2c_probe,
+       .remove         = s3c24xx_i2c_remove,
++      .suspend        = s3c24xx_i2c_suspend,
+       .resume         = s3c24xx_i2c_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+-- 
+1.5.6.5
+