summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/i2c/busses/i2c-designware-amdisp.c11
-rw-r--r--drivers/i2c/busses/i2c-imx.c51
3 files changed, 37 insertions, 27 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d31ceeac4a5..c3fe46d7c4bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12020,7 +12020,6 @@ I2C SUBSYSTEM
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
L: linux-i2c@vger.kernel.org
S: Maintained
-W: https://i2c.wiki.kernel.org/
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
F: Documentation/i2c/
@@ -12046,7 +12045,6 @@ I2C SUBSYSTEM HOST DRIVERS
M: Andi Shyti <andi.shyti@kernel.org>
L: linux-i2c@vger.kernel.org
S: Maintained
-W: https://i2c.wiki.kernel.org/
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
F: Documentation/devicetree/bindings/i2c/
diff --git a/drivers/i2c/busses/i2c-designware-amdisp.c b/drivers/i2c/busses/i2c-designware-amdisp.c
index c48728ad9f6f..9f0ec0fae6f2 100644
--- a/drivers/i2c/busses/i2c-designware-amdisp.c
+++ b/drivers/i2c/busses/i2c-designware-amdisp.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/soc/amd/isp4_misc.h>
@@ -76,22 +77,20 @@ static int amd_isp_dw_i2c_plat_probe(struct platform_device *pdev)
device_enable_async_suspend(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
+ dev_pm_genpd_resume(&pdev->dev);
ret = i2c_dw_probe(isp_i2c_dev);
if (ret) {
dev_err_probe(&pdev->dev, ret, "i2c_dw_probe failed\n");
goto error_release_rpm;
}
-
- pm_runtime_put_sync(&pdev->dev);
+ dev_pm_genpd_suspend(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
return 0;
error_release_rpm:
amd_isp_dw_i2c_plat_pm_cleanup(isp_i2c_dev);
- pm_runtime_put_sync(&pdev->dev);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 85f554044cf1..452d120a210b 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1018,8 +1018,9 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)
return 0;
}
-static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
+static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
{
+ enum imx_i2c_state next_state = IMX_I2C_STATE_READ_CONTINUE;
unsigned int temp;
if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {
@@ -1033,18 +1034,20 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- } else {
- /*
- * For i2c master receiver repeat restart operation like:
- * read -> repeat MSTA -> read/write
- * The controller must set MTX before read the last byte in
- * the first read operation, otherwise the first read cost
- * one extra clock cycle.
- */
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- temp |= I2CR_MTX;
- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+
+ return IMX_I2C_STATE_DONE;
}
+ /*
+ * For i2c master receiver repeat restart operation like:
+ * read -> repeat MSTA -> read/write
+ * The controller must set MTX before read the last byte in
+ * the first read operation, otherwise the first read cost
+ * one extra clock cycle.
+ */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_MTX;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ next_state = IMX_I2C_STATE_DONE;
} else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_TXAK;
@@ -1052,6 +1055,7 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
}
i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+ return next_state;
}
static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)
@@ -1088,11 +1092,9 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i
break;
case IMX_I2C_STATE_READ_CONTINUE:
- i2c_imx_isr_read_continue(i2c_imx);
- if (i2c_imx->msg_buf_idx == i2c_imx->msg->len) {
- i2c_imx->state = IMX_I2C_STATE_DONE;
+ i2c_imx->state = i2c_imx_isr_read_continue(i2c_imx);
+ if (i2c_imx->state == IMX_I2C_STATE_DONE)
wake_up(&i2c_imx->queue);
- }
break;
case IMX_I2C_STATE_READ_BLOCK_DATA:
@@ -1490,6 +1492,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
bool is_lastmsg)
{
int block_data = msgs->flags & I2C_M_RECV_LEN;
+ int ret = 0;
dev_dbg(&i2c_imx->adapter.dev,
"<%s> write slave address: addr=0x%x\n",
@@ -1522,10 +1525,20 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__);
return -ETIMEDOUT;
}
- if (!i2c_imx->stopped)
- return i2c_imx_bus_busy(i2c_imx, 0, false);
+ if (i2c_imx->is_lastmsg) {
+ if (!i2c_imx->stopped)
+ ret = i2c_imx_bus_busy(i2c_imx, 0, false);
+ /*
+ * Only read the last byte of the last message after the bus is
+ * not busy. Else the controller generates another clock which
+ * might confuse devices.
+ */
+ if (!ret)
+ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx,
+ IMX_I2C_I2DR);
+ }
- return 0;
+ return ret;
}
static int i2c_imx_xfer_common(struct i2c_adapter *adapter,