Re: [PATCH 04/12] I2C re-init for every cmd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"ext Rajendra Nayak" <rnayak@xxxxxx> writes:

> This patch does i2c init/re-init for every transfer
>
> Signed-off-by: Rajendra Nayak <rnayak@xxxxxx>
> ---
>  drivers/i2c/busses/i2c-omap.c |    2 ++
>  1 files changed, 2 insertions(+)
>
> Index: linux-omap-2.6/drivers/i2c/busses/i2c-omap.c
> ===================================================================
> --- linux-omap-2.6.orig/drivers/i2c/busses/i2c-omap.c	2008-09-01
> 18:11:28.000000000 +0530
> +++ linux-omap-2.6/drivers/i2c/busses/i2c-omap.c	2008-09-01 18:11:52.000000000
> +0530
> @@ -496,6 +496,8 @@ omap_i2c_xfer(struct i2c_adapter *adap,
>
>  	omap_i2c_unidle(dev);
>
> +	omap_i2c_init(dev);
> +
>  	if ((r = omap_i2c_wait_for_bb(dev)) < 0)
>  		goto out;

This is causing unacceptable delays on i2c transfers. This is because
occasionally reset loop in init function enters msleep. Is it
necessary to reset i2c controller after off-mode?

Any opinions on this:

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 3778735..4a27035 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -126,6 +126,14 @@
 /* I2C System Configuration Register (OMAP_I2C_SYSC): */
 #define OMAP_I2C_SYSC_SRST             (1 << 1)        /* Soft Reset */
 
+struct omap3_i2c_regs {
+       u16 sysc;
+       u16 psc;
+       u16 scll;
+       u16 sclh;
+       u16 buf;
+};
+
 struct omap_i2c_dev {
        struct device           *dev;
        void __iomem            *base;          /* virtual */
@@ -147,6 +155,9 @@ struct omap_i2c_dev {
        unsigned                b_hw:1;         /* bad h/w fixes */
        unsigned                idle:1;
        u16                     iestate;        /* Saved interrupt register */
+#ifdef CONFIG_ARCH_OMAP34XX
+       struct omap3_i2c_regs   context;
+#endif
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -160,6 +171,26 @@ 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_OMAP34XX
+void omap3_i2c_save_context(struct omap_i2c_dev *dev)
+{
+       dev->context.sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG);
+       dev->context.psc = omap_i2c_read_reg(dev, OMAP_I2C_PSC_REG);
+       dev->context.scll = omap_i2c_read_reg(dev, OMAP_I2C_SCLL_REG);
+       dev->context.sclh = omap_i2c_read_reg(dev, OMAP_I2C_SCLH_REG);
+       dev->context.buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+}
+
+void omap3_i2c_restore_context(struct omap_i2c_dev *dev)
+{
+       omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->context.sysc);
+       omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->context.psc);
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->context.scll);
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->context.sclh);
+       omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->context.buf);
+}
+#endif
+
 static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
 {
        if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
@@ -210,6 +241,10 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
                clk_enable(dev->iclk);
        clk_enable(dev->fclk);
        dev->idle = 0;
+
+       if (cpu_is_omap34xx())
+               omap3_i2c_restore_context(dev);
+
        if (dev->iestate)
                omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
 }
@@ -344,6 +379,10 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                        OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
                        OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
                                (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
+
+       if (cpu_is_omap34xx())
+               omap3_i2c_save_context(dev);
+
        return 0;
 }
 
@@ -496,8 +535,6 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        omap_i2c_unidle(dev);
 
-       omap_i2c_init(dev);
-
        if ((r = omap_i2c_wait_for_bb(dev)) < 0)
                goto out;

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux