summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-mxc/include/mach/i2c.h2
-rw-r--r--drivers/i2c/busses/i2c-imx.c6
2 files changed, 8 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/include/mach/i2c.h b/arch/arm/plat-mxc/include/mach/i2c.h
index 4a5dc5c6d8e8..7ed4f64c86a2 100644
--- a/arch/arm/plat-mxc/include/mach/i2c.h
+++ b/arch/arm/plat-mxc/include/mach/i2c.h
@@ -13,12 +13,14 @@
* struct imxi2c_platform_data - structure of platform data for MXC I2C driver
* @init: Initialise gpio's and other board specific things
* @exit: Free everything initialised by @init
+ * @reset: Issue I2C reset if needed (toggle SCL via GPIO access)
* @bitrate: Bus speed measured in Hz
*
**/
struct imxi2c_platform_data {
int (*init)(struct device *dev);
void (*exit)(struct device *dev);
+ int (*reset)(struct device *dev);
int bitrate;
};
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 8cec1965dec3..2e20a7843ca9 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -124,6 +124,7 @@ struct imx_i2c_struct {
int stopped;
unsigned int ifdr; /* IMX_I2C_IFDR */
unsigned int cur_clk;
+ int (*reset)(struct device *dev);
};
/** Functions for IMX I2C adapter driver ***************************************
@@ -253,6 +254,10 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
/* Wait controller to be stable */
udelay(50);
+ /* Check if bus is busy (hung if not multi-master) and issue reset */
+ if (i2c_imx->reset && i2c_imx->reset(&i2c_imx->adapter.dev))
+ return -ETIMEDOUT;
+
/* Start I2C transaction */
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
temp |= I2CR_MSTA;
@@ -541,6 +546,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx->irq = irq;
i2c_imx->base = base;
i2c_imx->res = res;
+ i2c_imx->reset = pdata->reset;
/* Get I2C clock */
i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk");