Commit 4c10830f authored by Wolfram Sang's avatar Wolfram Sang
Browse files

Merge tag 'i2c-host-fixes-7.0-rc6' of...

Merge tag 'i2c-host-fixes-7.0-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-current

i2c-fixes for v7.0-rc6

designware: fix resume-probe race causing NULL-deref in amdisp
imx: fix timeout on repeated reads and extra clock at end
parents c3692998 e2f1ada8
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -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;
}

+32 −19
Original line number Diff line number Diff line
@@ -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,7 +1034,9 @@ 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 {

			return IMX_I2C_STATE_DONE;
		}
		/*
		 * For i2c master receiver repeat restart operation like:
		 * 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 |= 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->is_lastmsg) {
		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,