diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 36 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 4 |
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); /* ------------------------------------------------------------------------- */ |