Commit ed866f41 authored by Manikanta Guntupalli's avatar Manikanta Guntupalli Committed by Andi Shyti
Browse files

i2c: cadence: Split cdns_i2c_master_xfer for Atomic Mode



The cdns_i2c_master_xfer function has been refactored to separate
the common code. This change facilitates better support for atomic
mode operations by isolating the shared logic.

Signed-off-by: default avatarManikanta Guntupalli <manikanta.guntupalli@amd.com>
Reviewed-by: default avatarAndi Shyti <andi.shyti@kernel.org>
Acked-by: default avatarMichal Simek <michal.simek@amd.com>
Signed-off-by: default avatarAndi Shyti <andi.shyti@kernel.org>
parent ae8ec9dd
Loading
Loading
Loading
Loading
+53 −47
Original line number Diff line number Diff line
@@ -866,46 +866,14 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
	return 0;
}

/**
 * cdns_i2c_master_xfer - The main i2c transfer function
 * @adap:	pointer to the i2c adapter driver instance
 * @msgs:	pointer to the i2c message structure
 * @num:	the number of messages to transfer
 *
 * Initiates the send/recv activity based on the transfer message received.
 *
 * Return: number of msgs processed on success, negative error otherwise
 */
static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
static int cdns_i2c_master_common_xfer(struct i2c_adapter *adap,
				       struct i2c_msg *msgs,
				       int num)
{
	int ret, count;
	u32 reg;
	struct cdns_i2c *id = adap->algo_data;
	bool hold_quirk;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	bool change_role = false;
#endif

	ret = pm_runtime_resume_and_get(id->dev);
	if (ret < 0)
		return ret;

#if IS_ENABLED(CONFIG_I2C_SLAVE)
	/* Check i2c operating mode and switch if possible */
	if (id->dev_mode == CDNS_I2C_MODE_SLAVE) {
		if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) {
			ret = -EAGAIN;
			goto out;
		}

		/* Set mode to master */
		cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);

		/* Mark flag to change role once xfer is completed */
		change_role = true;
	}
#endif

	/* Check if the bus is free */

@@ -917,7 +885,7 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
		ret = -EAGAIN;
		if (id->adap.bus_recovery_info)
			i2c_recover_bus(adap);
		goto out;
		return ret;
	}

	hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
@@ -937,8 +905,7 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
			if (msgs[count].flags & I2C_M_RD) {
				dev_warn(adap->dev.parent,
					 "Can't do repeated start after a receive message\n");
				ret = -EOPNOTSUPP;
				goto out;
				return -EOPNOTSUPP;
			}
		}
		id->bus_hold_flag = 1;
@@ -956,26 +923,65 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,

		ret = cdns_i2c_process_msg(id, msgs, adap);
		if (ret)
			goto out;
			return ret;

		/* Report the other error interrupts to application */
		if (id->err_status) {
			cdns_i2c_master_reset(adap);

			if (id->err_status & CDNS_I2C_IXR_NACK) {
				ret = -ENXIO;
				goto out;
			if (id->err_status & CDNS_I2C_IXR_NACK)
				return -ENXIO;

			return -EIO;
		}
			ret = -EIO;
			goto out;
	}
	return 0;
}

	ret = num;
/**
 * cdns_i2c_master_xfer - The main i2c transfer function
 * @adap:	pointer to the i2c adapter driver instance
 * @msgs:	pointer to the i2c message structure
 * @num:	the number of messages to transfer
 *
 * Initiates the send/recv activity based on the transfer message received.
 *
 * Return: number of msgs processed on success, negative error otherwise
 */
static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
				int num)
{
	int ret;
	struct cdns_i2c *id = adap->algo_data;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	bool change_role = false;
#endif

out:
	ret = pm_runtime_resume_and_get(id->dev);
	if (ret < 0)
		return ret;

#if IS_ENABLED(CONFIG_I2C_SLAVE)
	/* Check i2c operating mode and switch if possible */
	if (id->dev_mode == CDNS_I2C_MODE_SLAVE) {
		if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) {
			ret = -EAGAIN;
			goto out;
		}

		/* Set mode to master */
		cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);

		/* Mark flag to change role once xfer is completed */
		change_role = true;
	}
#endif

	ret = cdns_i2c_master_common_xfer(adap, msgs, num);
	if (!ret)
		ret = num;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
out:
	/* Switch i2c mode to slave */
	if (change_role)
		cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id);