i2c-for-7.0-rc6
designware: fix resume-probe race causing NULL-deref in amdisp imx: fix timeout on repeated reads and extra clock at end MAINTAINERS: drop outdated I2C website -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmnIwYAACgkQFA3kzBSg KbZWMw/+P/+jIvjGm9ySmj4cOZIKydpGxdauDPcyzmWwu2bfyjplmqvtUJxUmiRI jf+4uod4SJeibFUm6OVk+EgrXuUWEV+qIJ+IPlBvdBbhftVTQUN1o751rOUGxj6D X8uqmDRLnC0ujG6Y1QvZGNkYl2RUmDBVHYgCk0kY+mYeoV7+TihVvmuhX+ksRhga s+fMl9M18Z4H7m7muZzRJe/phvo8GK2RvM+jXIW/wD2sJCoRc6x3OZ6VIqiHZcZS PVfCIFxaSokAXx95eWpjqJhRkvwEFMG09EI6TASmxtnYbZKGX8wHaoY0bctUbOPu SQ/vHQsnkzNxyHBX7mVFot10nA90C88MqoD/oEpVYAPv0Xg5GuaIvV20+FMg/2HT KeNHBb3TTOa79Bl1tWiQZ9a8TcfyaVZ/TeTeuntFNYoiJJDhQrk0nbXsRuMz1zmf viMD0YjkuNrlvIiEbR/Y27AC/vUTk4elRaWb+inAvZonjvNi/bhjxFhxsC+Jb163 cP9bt9zjfEqcIAnHTKwLcFtSRmZCiSFPeJ0VFCZZxUehybhjZJflSTSJeKaiw1ni mJqoMt3oXo4rIuwOouxrKT4WfptLu2mstOfQPlvyGVEulGl1p+Sx3JYzthhF0gVM OyR/UzLg4lRFlO84qlLjNZTPoxa3G8f2EdP0dSGiPz0kXuvl3DM= =3asa -----END PGP SIGNATURE----- Merge tag 'i2c-for-7.0-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c fixes from Wolfram Sang: - designware: fix resume-probe race causing NULL-deref in amdisp - imx: fix timeout on repeated reads and extra clock at end - MAINTAINERS: drop outdated I2C website * tag 'i2c-for-7.0-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: MAINTAINERS: drop outdated I2C website i2c: designware: amdisp: Fix resume-probe race condition issue i2c: imx: ensure no clock is generated after last read i2c: imx: fix i2c issue when reading multiple messages
This commit is contained in:
commit
32ee88daf7
|
|
@ -12020,7 +12020,6 @@ I2C SUBSYSTEM
|
||||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||||
L: linux-i2c@vger.kernel.org
|
L: linux-i2c@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
W: https://i2c.wiki.kernel.org/
|
|
||||||
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
|
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
|
||||||
F: Documentation/i2c/
|
F: Documentation/i2c/
|
||||||
|
|
@ -12046,7 +12045,6 @@ I2C SUBSYSTEM HOST DRIVERS
|
||||||
M: Andi Shyti <andi.shyti@kernel.org>
|
M: Andi Shyti <andi.shyti@kernel.org>
|
||||||
L: linux-i2c@vger.kernel.org
|
L: linux-i2c@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
W: https://i2c.wiki.kernel.org/
|
|
||||||
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
|
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
|
||||||
F: Documentation/devicetree/bindings/i2c/
|
F: Documentation/devicetree/bindings/i2c/
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/soc/amd/isp4_misc.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);
|
device_enable_async_suspend(&pdev->dev);
|
||||||
|
|
||||||
pm_runtime_enable(&pdev->dev);
|
dev_pm_genpd_resume(&pdev->dev);
|
||||||
pm_runtime_get_sync(&pdev->dev);
|
|
||||||
|
|
||||||
ret = i2c_dw_probe(isp_i2c_dev);
|
ret = i2c_dw_probe(isp_i2c_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_probe(&pdev->dev, ret, "i2c_dw_probe failed\n");
|
dev_err_probe(&pdev->dev, ret, "i2c_dw_probe failed\n");
|
||||||
goto error_release_rpm;
|
goto error_release_rpm;
|
||||||
}
|
}
|
||||||
|
dev_pm_genpd_suspend(&pdev->dev);
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_set_suspended(&pdev->dev);
|
||||||
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_release_rpm:
|
error_release_rpm:
|
||||||
amd_isp_dw_i2c_plat_pm_cleanup(isp_i2c_dev);
|
amd_isp_dw_i2c_plat_pm_cleanup(isp_i2c_dev);
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1018,8 +1018,9 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)
|
||||||
return 0;
|
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;
|
unsigned int temp;
|
||||||
|
|
||||||
if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {
|
if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {
|
||||||
|
|
@ -1033,7 +1034,9 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
|
||||||
i2c_imx->stopped = 1;
|
i2c_imx->stopped = 1;
|
||||||
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
||||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||||
} else {
|
|
||||||
|
return IMX_I2C_STATE_DONE;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* For i2c master receiver repeat restart operation like:
|
* For i2c master receiver repeat restart operation like:
|
||||||
* read -> repeat MSTA -> read/write
|
* read -> repeat MSTA -> read/write
|
||||||
|
|
@ -1044,7 +1047,7 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
|
||||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||||
temp |= I2CR_MTX;
|
temp |= I2CR_MTX;
|
||||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
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)) {
|
} else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) {
|
||||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||||
temp |= I2CR_TXAK;
|
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);
|
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)
|
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;
|
break;
|
||||||
|
|
||||||
case IMX_I2C_STATE_READ_CONTINUE:
|
case IMX_I2C_STATE_READ_CONTINUE:
|
||||||
i2c_imx_isr_read_continue(i2c_imx);
|
i2c_imx->state = i2c_imx_isr_read_continue(i2c_imx);
|
||||||
if (i2c_imx->msg_buf_idx == i2c_imx->msg->len) {
|
if (i2c_imx->state == IMX_I2C_STATE_DONE)
|
||||||
i2c_imx->state = IMX_I2C_STATE_DONE;
|
|
||||||
wake_up(&i2c_imx->queue);
|
wake_up(&i2c_imx->queue);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMX_I2C_STATE_READ_BLOCK_DATA:
|
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)
|
bool is_lastmsg)
|
||||||
{
|
{
|
||||||
int block_data = msgs->flags & I2C_M_RECV_LEN;
|
int block_data = msgs->flags & I2C_M_RECV_LEN;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
dev_dbg(&i2c_imx->adapter.dev,
|
dev_dbg(&i2c_imx->adapter.dev,
|
||||||
"<%s> write slave address: addr=0x%x\n",
|
"<%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__);
|
dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
if (i2c_imx->is_lastmsg) {
|
||||||
if (!i2c_imx->stopped)
|
if (!i2c_imx->stopped)
|
||||||
return i2c_imx_bus_busy(i2c_imx, 0, false);
|
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,
|
static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue