On Fri, Feb 24, 2012 at 5:01 PM, Viresh Kumar <viresh.kumar@xxxxxx> wrote: > From: Vincenzo Frascino <vincenzo.frascino@xxxxxx> > > Add optional i2c_recover_bus() function to the Synopsys DesignWare I2C adapter > driver that performs i2c bus recovery after timeout. The scope of this routine > is to define i2c bus recovery procedure as specified in the i2c protocol Rev. 03 > section 3.16 titled "Bus clear". What do you do in the function ? Could we have it in the driver file itself? > > Since the Designware I2C controller doesn't provide direct control over SDA and > SCL lines hence the intent is to let platform try to recover the bus if they > have the capability to take control of I2C pads and follow the recovery > protocol. So the function is passed in the pdata. > > Signed-off-by: Vincenzo Frascino <vincenzo.frascino@xxxxxx> > Signed-off-by: Shiraz Hashim <shiraz.hashim@xxxxxx> > Signed-off-by: Viresh Kumar <viresh.kumar@xxxxxx> > --- > drivers/i2c/busses/i2c-designware-core.c | 4 +++ > drivers/i2c/busses/i2c-designware-core.h | 3 +- > drivers/i2c/busses/i2c-designware-platdrv.c | 8 ++++++ > include/linux/i2c/i2c-designware.h | 33 +++++++++++++++++++++++++++ > 4 files changed, 47 insertions(+), 1 deletions(-) > create mode 100644 include/linux/i2c/i2c-designware.h > > diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c > index df87992..91d9357 100644 > --- a/drivers/i2c/busses/i2c-designware-core.c > +++ b/drivers/i2c/busses/i2c-designware-core.c > @@ -525,6 +525,10 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) > ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); > if (ret == 0) { > dev_err(dev->dev, "controller timed out\n"); > + if (dev->i2c_recover_bus) { > + dev_info(dev->dev, "try i2c bus recovery\n"); > + dev->i2c_recover_bus(dev->recovery_data); > + } > i2c_dw_init(dev); > ret = -ETIMEDOUT; > goto done; > diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h > index 02d1a2d..e2f3119 100644 > --- a/drivers/i2c/busses/i2c-designware-core.h > +++ b/drivers/i2c/busses/i2c-designware-core.h > @@ -34,7 +34,6 @@ > #define DW_IC_CON_RESTART_EN 0x20 > #define DW_IC_CON_SLAVE_DISABLE 0x40 > > - > /** > * struct dw_i2c_dev - private i2c-designware data > * @dev: driver model device node > @@ -88,6 +87,8 @@ struct dw_i2c_dev { > u32 master_cfg; > unsigned int tx_fifo_depth; > unsigned int rx_fifo_depth; > + void (*i2c_recover_bus)(void *); > + void *recovery_data; > }; > > extern u32 dw_readl(struct dw_i2c_dev *dev, int offset); > diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c > index c5ac2dc..2237398 100644 > --- a/drivers/i2c/busses/i2c-designware-platdrv.c > +++ b/drivers/i2c/busses/i2c-designware-platdrv.c > @@ -29,6 +29,7 @@ > #include <linux/module.h> > #include <linux/delay.h> > #include <linux/i2c.h> > +#include <linux/i2c/i2c-designware.h> > #include <linux/clk.h> > #include <linux/errno.h> > #include <linux/sched.h> > @@ -55,6 +56,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) > struct dw_i2c_dev *dev; > struct i2c_adapter *adap; > struct resource *mem, *ioarea; > + struct i2c_dw_pdata *pdata; > int irq, r; > > /* NOTE: driver uses the static register mapping */ > @@ -98,6 +100,12 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) > } > clk_enable(dev->clk); > > + pdata = dev_get_platdata(&pdev->dev); > + if (pdata && pdata->i2c_recover_bus) { > + dev->i2c_recover_bus = pdata->i2c_recover_bus; > + dev->recovery_data = &pdev; > + } > + > dev->functionality = > I2C_FUNC_I2C | > I2C_FUNC_10BIT_ADDR | > diff --git a/include/linux/i2c/i2c-designware.h b/include/linux/i2c/i2c-designware.h > new file mode 100644 > index 0000000..e40ad85 > --- /dev/null > +++ b/include/linux/i2c/i2c-designware.h > @@ -0,0 +1,33 @@ > +/* > + * Synopsys DesignWare I2C adapter driver's platform data > + * > + * Copyright (C) 2012 ST Microelectronics. > + * Author: Vincenzo Frascino <vincenzo.frascino@xxxxxx> > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > +#ifndef I2C_DESIGNWARE_H > +#define I2C_DESIGNWARE_H > + > +#include <linux/platform_device.h> > + > +/* I2C Designware Platform Data */ > +struct i2c_dw_pdata { > + /* > + * The scope of this routine is to define i2c bus recovery procedure > + * as specified in the i2c protocol Rev. 03 section 3.16 titled > + * "Bus clear". > + * Its implementation is platform dependant. > + */ > + void (*i2c_recover_bus)(void *); > +}; > + > +#endif /* I2C_DESIGNWARE_H */ > -- > 1.7.8.110.g4cb5d > > -- > To unsubscribe from this list: send the line "unsubscribe linux-i2c" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html