diff --git a/arch/arm/mach-davinci/include/mach/i2c.h b/arch/arm/mach-davinci/include/mach/i2c.h
index ab07a44..858c5c6 100644
--- a/arch/arm/mach-davinci/include/mach/i2c.h
+++ b/arch/arm/mach-davinci/include/mach/i2c.h
@@ -19,12 +19,16 @@
  * @bus_delay:	post-transaction delay (usec)
  * @sda_pin:	GPIO pin ID to use for SDA
  * @scl_pin:	GPIO pin ID to use for SCL
+ * @has_pfunc:	set this to true if the i2c controller on your chip has a
+ *		ICPFUNC register which allows the SDA and SCL pins to be
+ *		controlled as gpio (like in DA850)
  */
 struct davinci_i2c_platform_data {
 	unsigned int	bus_freq;
 	unsigned int	bus_delay;
 	unsigned int	sda_pin;
 	unsigned int	scl_pin;
+	bool		has_pfunc;
 };
 
 /* for board setup code */
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 0a2c697..5bdc98c 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -65,6 +65,11 @@
 #define DAVINCI_I2C_IVR_REG	0x28
 #define DAVINCI_I2C_EMDR_REG	0x2c
 #define DAVINCI_I2C_PSC_REG	0x30
+#define DAVINCI_I2C_PFUNC_REG	0x48
+#define DAVINCI_I2C_PDIR_REG	0x4c
+#define DAVINCI_I2C_PDIN_REG	0x50
+#define DAVINCI_I2C_DSET_REG	0x58
+#define DAVINCI_I2C_DCLR_REG	0x5c
 
 #define DAVINCI_I2C_IVR_AAS	0x07
 #define DAVINCI_I2C_IVR_SCD	0x06
@@ -98,6 +103,29 @@
 #define DAVINCI_I2C_IMR_NACK	BIT(1)
 #define DAVINCI_I2C_IMR_AL	BIT(0)
 
+/* set SDA and SCL as GPIO */
+#define DAVINCI_I2C_PFUNC_PFUNC0	BIT(0)
+
+/* set SCL as output when used as GPIO*/
+#define DAVINCI_I2C_PDIR_PDIR0	BIT(0)
+/* set SDA as output when used as GPIO*/
+#define DAVINCI_I2C_PDIR_PDIR1	BIT(1)
+
+/* read SCL GPIO level */
+#define DAVINCI_I2C_PDIN_PDIN0 BIT(0)
+/* read SDA GPIO level */
+#define DAVINCI_I2C_PDIN_PDIN1 BIT(1)
+
+/*set the SCL GPIO high */
+#define DAVINCI_I2C_DSET_PDSET0	BIT(0)
+/*set the SDA GPIO high */
+#define DAVINCI_I2C_DSET_PDSET1	BIT(1)
+
+/* set the SCL GPIO low */
+#define DAVINCI_I2C_DCLR_PDCLR0	BIT(0)
+/* set the SDA GPIO low */
+#define DAVINCI_I2C_DCLR_PDCLR1	BIT(1)
+
 struct davinci_i2c_dev {
 	struct device           *dev;
 	void __iomem		*base;
@@ -182,6 +210,64 @@ static void generic_i2c_clock_pulse(struct davinci_i2c_dev *dev)
 	}
 }
 
+static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
+								int val);
+
+/* Generate gpio a pulse on the i2c clock pin. */
+static void i2c_davinci_pfunc_i2c_clock_pulse(struct davinci_i2c_dev *dev)
+{
+	u32 flag = 0;
+	u16 i;
+
+	davinci_i2c_reset_ctrl(dev, 0);
+
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0x00);
+
+	/* SCL output, SDA input */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_PDIR_REG,
+				DAVINCI_I2C_PDIR_PDIR0);
+
+	/* change to GPIO mode */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_PFUNC_REG,
+				DAVINCI_I2C_PFUNC_PFUNC0);
+
+	/* SCL high */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG,
+				DAVINCI_I2C_DSET_PDSET0);
+	udelay(5);
+	for (i = 0; i < 16; i++) {
+		/* SCL low */
+		davinci_i2c_write_reg(dev, DAVINCI_I2C_DCLR_REG,
+					DAVINCI_I2C_DCLR_PDCLR0);
+		udelay(5);
+		/* SCL high */
+		davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG,
+					DAVINCI_I2C_DSET_PDSET0);
+		udelay(5);
+
+		/* read the state of SDA */
+		flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_PDIN_REG);
+		if (flag & DAVINCI_I2C_PDIN_PDIN1) {
+			dev_dbg(dev->dev, "recovered after %d SCL pulses",
+					i + 1);
+			break;
+		}
+	}
+
+	/* change back to I2C mode */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_PFUNC_REG, 0);
+
+	/* take the I2C dev out of reset */
+	davinci_i2c_reset_ctrl(dev, 1);
+
+	/* read the state of SDA */
+	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_PDIN_REG);
+	if (flag & DAVINCI_I2C_PDIN_PDIN1)
+		return;
+
+	dev_err(dev->dev, "I2C slave will not release SDA.\n");
+}
+
 /* This routine does i2c bus recovery as specified in the
  * i2c protocol Rev. 03 section 3.16 titled "Bus clear"
  */
@@ -756,6 +842,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 	pdata = dev->dev->platform_data;
 	if (pdata->scl_pin)
 		dev->pulse_scl = generic_i2c_clock_pulse;
+	else if (pdata->has_pfunc)
+		dev->pulse_scl = i2c_davinci_pfunc_i2c_clock_pulse;
 
 	return 0;
 
