"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