aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c36
-rw-r--r--drivers/i2c/i2c-core.c4
2 files changed, 40 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ead17f9354b..6b325c4dafe 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -38,6 +38,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/hwspinlock.h>
#include <linux/i2c-omap.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos_params.h>
@@ -264,6 +265,31 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
(i2c_dev->regs[reg] << i2c_dev->reg_shift));
}
+static int omap_i2c_hwspinlock_lock(struct omap_i2c_dev *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev->dev);
+ struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
+ int ret = 0;
+
+ if (pdata->hwspin_lock_timeout) {
+ ret = pdata->hwspin_lock_timeout(pdata->handle, 100);
+ if (ret != 0)
+ dev_err(&pdev->dev, "%s: TIMEDOUT: Failed to acquire "
+ "hwspinlock\n", __func__);
+ return ret;
+ } else
+ return -EINVAL;
+}
+
+static void omap_i2c_hwspinlock_unlock(struct omap_i2c_dev *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev->dev);
+ struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
+
+ if (pdata->hwspin_unlock)
+ pdata->hwspin_unlock(pdata->handle);
+}
+
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
struct platform_device *pdev;
@@ -630,6 +656,15 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
int r;
u16 val;
+ if (dev == NULL)
+ return -EINVAL;
+
+ r = omap_i2c_hwspinlock_lock(dev);
+ /* To-Do: if we are unable to acquire the lock, we must
+ try to recover somehow */
+ if (r != 0)
+ return r;
+
omap_i2c_unidle(dev);
r = omap_i2c_wait_for_bb(dev);
@@ -672,6 +707,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_wait_for_bb(dev);
out:
omap_i2c_idle(dev);
+ omap_i2c_hwspinlock_unlock(dev);
return r;
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index d0ec08f65a2..87a5c7f364d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1131,6 +1131,7 @@ EXPORT_SYMBOL(i2c_del_adapter);
* This detects registered I2C devices which are controlled
* by a remote/external proc.
*/
+#if !defined(CONFIG_HWSPINLOCK)
void i2c_detect_ext_master(struct i2c_adapter *adap)
{
struct i2c_adapter *found;
@@ -1160,6 +1161,9 @@ void i2c_detect_ext_master(struct i2c_adapter *adap)
return;
}
+#else
+void i2c_detect_ext_master(struct i2c_adapter *adap) { return; }
+#endif
EXPORT_SYMBOL(i2c_detect_ext_master);
/* ------------------------------------------------------------------------- */