aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorDavid Box <david.e.box@linux.intel.com>2015-01-15 04:12:16 -0500
committerWolfram Sang <wsa@the-dreams.de>2015-01-26 06:26:16 -0500
commitc0601d285efe063def984f91b04de2d227f89526 (patch)
treef405abc5b7a41d51893e3e59821781075b1571e6 /drivers/i2c
parent72f0271576eeef40c81c2949e0a8abeaef9a7690 (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.c26
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h6
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}
369EXPORT_SYMBOL_GPL(i2c_dw_init); 383EXPORT_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
674done: 696done:
697 if (dev->release_lock)
698 dev->release_lock(dev);
699
700done_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