diff options
author | David Box <david.e.box@linux.intel.com> | 2015-01-15 04:12:16 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2015-01-26 06:26:16 -0500 |
commit | c0601d285efe063def984f91b04de2d227f89526 (patch) | |
tree | f405abc5b7a41d51893e3e59821781075b1571e6 /drivers/i2c | |
parent | 72f0271576eeef40c81c2949e0a8abeaef9a7690 (diff) |
i2c: designware: Add i2c bus locking support
Adds support for acquiring and releasing a hardware bus lock in the i2c
designware core transfer function. This is needed for i2c bus controllers
that are shared with but not controlled by the kernel.
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 26 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 6 |
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index e2799483dc45..fbb48fb138e7 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -285,6 +285,15 @@ int i2c_dw_init(struct dw_i2c_dev *dev) | |||
285 | u32 hcnt, lcnt; | 285 | u32 hcnt, lcnt; |
286 | u32 reg; | 286 | u32 reg; |
287 | u32 sda_falling_time, scl_falling_time; | 287 | u32 sda_falling_time, scl_falling_time; |
288 | int ret; | ||
289 | |||
290 | if (dev->acquire_lock) { | ||
291 | ret = dev->acquire_lock(dev); | ||
292 | if (ret) { | ||
293 | dev_err(dev->dev, "couldn't acquire bus ownership\n"); | ||
294 | return ret; | ||
295 | } | ||
296 | } | ||
288 | 297 | ||
289 | input_clock_khz = dev->get_clk_rate_khz(dev); | 298 | input_clock_khz = dev->get_clk_rate_khz(dev); |
290 | 299 | ||
@@ -298,6 +307,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev) | |||
298 | } else if (reg != DW_IC_COMP_TYPE_VALUE) { | 307 | } else if (reg != DW_IC_COMP_TYPE_VALUE) { |
299 | dev_err(dev->dev, "Unknown Synopsys component type: " | 308 | dev_err(dev->dev, "Unknown Synopsys component type: " |
300 | "0x%08x\n", reg); | 309 | "0x%08x\n", reg); |
310 | if (dev->release_lock) | ||
311 | dev->release_lock(dev); | ||
301 | return -ENODEV; | 312 | return -ENODEV; |
302 | } | 313 | } |
303 | 314 | ||
@@ -364,6 +375,9 @@ int i2c_dw_init(struct dw_i2c_dev *dev) | |||
364 | 375 | ||
365 | /* configure the i2c master */ | 376 | /* configure the i2c master */ |
366 | dw_writel(dev, dev->master_cfg , DW_IC_CON); | 377 | dw_writel(dev, dev->master_cfg , DW_IC_CON); |
378 | |||
379 | if (dev->release_lock) | ||
380 | dev->release_lock(dev); | ||
367 | return 0; | 381 | return 0; |
368 | } | 382 | } |
369 | EXPORT_SYMBOL_GPL(i2c_dw_init); | 383 | EXPORT_SYMBOL_GPL(i2c_dw_init); |
@@ -627,6 +641,14 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
627 | dev->abort_source = 0; | 641 | dev->abort_source = 0; |
628 | dev->rx_outstanding = 0; | 642 | dev->rx_outstanding = 0; |
629 | 643 | ||
644 | if (dev->acquire_lock) { | ||
645 | ret = dev->acquire_lock(dev); | ||
646 | if (ret) { | ||
647 | dev_err(dev->dev, "couldn't acquire bus ownership\n"); | ||
648 | goto done_nolock; | ||
649 | } | ||
650 | } | ||
651 | |||
630 | ret = i2c_dw_wait_bus_not_busy(dev); | 652 | ret = i2c_dw_wait_bus_not_busy(dev); |
631 | if (ret < 0) | 653 | if (ret < 0) |
632 | goto done; | 654 | goto done; |
@@ -672,6 +694,10 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
672 | ret = -EIO; | 694 | ret = -EIO; |
673 | 695 | ||
674 | done: | 696 | done: |
697 | if (dev->release_lock) | ||
698 | dev->release_lock(dev); | ||
699 | |||
700 | done_nolock: | ||
675 | pm_runtime_mark_last_busy(dev->dev); | 701 | pm_runtime_mark_last_busy(dev->dev); |
676 | pm_runtime_put_autosuspend(dev->dev); | 702 | pm_runtime_put_autosuspend(dev->dev); |
677 | mutex_unlock(&dev->lock); | 703 | mutex_unlock(&dev->lock); |
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 5a410ef17abd..ef8ba839e2d3 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h | |||
@@ -61,6 +61,9 @@ | |||
61 | * @ss_lcnt: standard speed LCNT value | 61 | * @ss_lcnt: standard speed LCNT value |
62 | * @fs_hcnt: fast speed HCNT value | 62 | * @fs_hcnt: fast speed HCNT value |
63 | * @fs_lcnt: fast speed LCNT value | 63 | * @fs_lcnt: fast speed LCNT value |
64 | * @acquire_lock: function to acquire a hardware lock on the bus | ||
65 | * @release_lock: function to release a hardware lock on the bus | ||
66 | * @pm_runtime_disabled: true if pm runtime is disabled | ||
64 | * | 67 | * |
65 | * HCNT and LCNT parameters can be used if the platform knows more accurate | 68 | * HCNT and LCNT parameters can be used if the platform knows more accurate |
66 | * values than the one computed based only on the input clock frequency. | 69 | * values than the one computed based only on the input clock frequency. |
@@ -101,6 +104,9 @@ struct dw_i2c_dev { | |||
101 | u16 ss_lcnt; | 104 | u16 ss_lcnt; |
102 | u16 fs_hcnt; | 105 | u16 fs_hcnt; |
103 | u16 fs_lcnt; | 106 | u16 fs_lcnt; |
107 | int (*acquire_lock)(struct dw_i2c_dev *dev); | ||
108 | void (*release_lock)(struct dw_i2c_dev *dev); | ||
109 | bool pm_runtime_disabled; | ||
104 | }; | 110 | }; |
105 | 111 | ||
106 | #define ACCESS_SWAP 0x00000001 | 112 | #define ACCESS_SWAP 0x00000001 |