From a3b07c78baca82328dd2820733dbc55500b6e35e Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 1 Mar 2006 13:57:44 +0200 Subject: [PATCH] i2c-omap: Use dynamic clocking also on OMAP1 CPUs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Juha Yrjölä --- drivers/i2c/busses/i2c-omap.c | 46 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index f416d19ac59..2502cb1c1e2 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -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); -- 2.41.1