]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
i2c-omap: Use dynamic clocking also on OMAP1 CPUs
authorJarkko Nikula <jarkko.nikula@nokia.com>
Wed, 1 Mar 2006 11:57:44 +0000 (13:57 +0200)
committerJuha Yrjola <juha.yrjola@nokia.com>
Wed, 1 Mar 2006 11:57:44 +0000 (13:57 +0200)
This patch will fix the i2c-omap "controller timed out" error on
OMAP1710 (most probably will apply to 1510 as well). Error happens
randomly if dyn_tick is activated (CONFIG_NO_IDLE_HZ=y) and reason was
that ARMXOR_CK clock domain was stopped during MPU idle.

Patch basically creates and uses virtual i2c_fck clock domain which
prevents that its parent ARMXOR_CK is not stopped during MPU idle
whenever i2c_fck is enabled. Patch also makes i2c-omap implementation
between 24xx and OMAP1 more consistent with the clock usage and fixes two
minor bugs.

Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Juha Yrjölä <juha.yrjola@nokia.com>
drivers/i2c/busses/i2c-omap.c

index f416d19ac591ce82fd1ba3cd2098204c83a25483..2502cb1c1e287dc8ab075b9437e0b029aacb64b8 100644 (file)
@@ -161,21 +161,24 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
        return __raw_readw(i2c_dev->base + reg);
 }
 
-#ifdef CONFIG_ARCH_OMAP24XX
 static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
 {
-       if (!cpu_is_omap24xx())
-               return 0;
-
-       dev->iclk = clk_get(dev->dev, "i2c_ick");
-       if (IS_ERR(dev->iclk)) {
-               return -ENODEV;
+       if (cpu_is_omap24xx()) {
+               dev->iclk = clk_get(dev->dev, "i2c_ick");
+               if (IS_ERR(dev->iclk)) {
+                       return -ENODEV;
+               }
+               dev->fclk = clk_get(dev->dev, "i2c_fck");
+               if (IS_ERR(dev->fclk)) {
+                       clk_put(dev->fclk);
+                       return -ENODEV;
+               }
        }
 
-       dev->fclk = clk_get(dev->dev, "i2c_fck");
-       if (IS_ERR(dev->fclk)) {
-               clk_put(dev->fclk);
-               return -ENODEV;
+       if (cpu_class_is_omap1()) {
+               dev->fclk = clk_get(dev->dev, "i2c_fck");
+               if (IS_ERR(dev->fclk))
+                       return -ENODEV;
        }
 
        return 0;
@@ -184,28 +187,27 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
 static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
 {
        clk_put(dev->fclk);
-       clk_put(dev->iclk);
+       dev->fclk = NULL;
+       if (dev->iclk != NULL) {
+               clk_put(dev->iclk);
+               dev->iclk = NULL;
+       }
 }
 
 static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
 {
-       clk_enable(dev->iclk);
+       if (dev->iclk != NULL)
+               clk_enable(dev->iclk);
        clk_enable(dev->fclk);
 }
 
 static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
 {
-       clk_disable(dev->iclk);
+       if (dev->iclk != NULL)
+               clk_disable(dev->iclk);
        clk_disable(dev->fclk);
 }
 
-#else
-#define omap_i2c_get_clocks(x)         0
-#define omap_i2c_enable_clocks(x)      do {} while (0)
-#define omap_i2c_disable_clocks(x)     do {} while (0)
-#define omap_i2c_put_clocks(x)         do {} while (0)
-#endif
-
 static void omap_i2c_reset(struct omap_i2c_dev *dev)
 {
        u16 psc;
@@ -665,7 +667,7 @@ omap_i2c_probe(struct platform_device *pdev)
 do_free_irq:
        free_irq(dev->irq, dev);
 do_unuse_clocks:
-       omap_i2c_enable_clocks(dev);
+       omap_i2c_disable_clocks(dev);
        omap_i2c_put_clocks(dev);
 do_free_mem:
        kfree(dev);