Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
Changes in v2:
-Change error return to -ESHUTDOWN
-Add a blurb to the commit message to mention that the errors in the commitmsg
are examples of errors which will be easier to debug with this change and
that this change does not actually fixes these errors
-Add a blurb to the commit message about why i2c_lock_bus() is not called
from the suspend/resume methods
---
drivers/i2c/busses/i2c-designware-core.h | 2 ++
drivers/i2c/busses/i2c-designware-master.c | 6 ++++++
drivers/i2c/busses/i2c-designware-pcidrv.c | 7 ++++++-
drivers/i2c/busses/i2c-designware-platdrv.c | 3 +++
4 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index b4a0b2b99a78..6b4ef1d38fb2 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -215,6 +215,7 @@
* @disable_int: function to disable all interrupts
* @init: function to initialize the I2C hardware
* @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
+ * @suspended: set to true if the controller is suspended
*
* HCNT and LCNT parameters can be used if the platform knows more accurate
* values than the one computed based only on the input clock frequency.
@@ -270,6 +271,7 @@ struct dw_i2c_dev {
int (*set_sda_hold_time)(struct dw_i2c_dev *dev);
int mode;
struct i2c_bus_recovery_info rinfo;
+ bool suspended;
};
#define ACCESS_SWAP 0x00000001
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 8d1bc44d2530..bb8e3f149979 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -426,6 +426,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
pm_runtime_get_sync(dev->dev);
+ if (dev->suspended) {
+ dev_err(dev->dev, "Error %s call while suspended\n", __func__);
+ ret = -ESHUTDOWN;
+ goto done_nolock;
+ }
+
reinit_completion(&dev->cmd_complete);
dev->msgs = msgs;
dev->msgs_num = num;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index d50f80487214..76810deb2de6 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -176,6 +176,7 @@ static int i2c_dw_pci_suspend(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev);
+ i_dev->suspended = true;
i_dev->disable(i_dev);
return 0;
@@ -185,8 +186,12 @@ static int i2c_dw_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev);
+ int ret;
- return i_dev->init(i_dev);
+ ret = i_dev->init(i_dev);
+ i_dev->suspended = false;
+
+ return ret;
}
#endif
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 9eaac3be1f63..ead5e7de3e4d 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -454,6 +454,8 @@ static int dw_i2c_plat_suspend(struct device *dev)
{
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
+ i_dev->suspended = true;
+
if (i_dev->shared_with_punit)
return 0;
@@ -471,6 +473,7 @@ static int dw_i2c_plat_resume(struct device *dev)
i2c_dw_prepare_clk(i_dev, true);
i_dev->init(i_dev);
+ i_dev->suspended = false;
return 0;
}
--
2.20.1