static inline void reset_hw_engine(struct engine *engine)
{
	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);

	REG_UPDATE_2(
			DC_I2C_CONTROL,
			DC_I2C_SW_STATUS_RESET, 1,
			DC_I2C_SW_STATUS_RESET, 1);
}
static bool is_hw_busy(struct engine *engine)
{
	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
	uint32_t i2c_sw_status = 0;

	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
		return false;

	reset_hw_engine(engine);

	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
}
static void keep_power_up_count(
	struct engine *engine,
	bool keep_power_up)
{
	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);

	if (keep_power_up)
		++hw_engine->engine_keep_power_up_count;
	else {
		--hw_engine->engine_keep_power_up_count;

		if (!hw_engine->engine_keep_power_up_count)
			disable_i2c_hw_engine(hw_engine);
	}
}
static void release_engine(
	struct engine *engine)
{
	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);

	struct i2c_engine *base = NULL;
	bool safe_to_reset;

	base = &hw_engine->base.base;

	/* Restore original HW engine speed */

	base->funcs->set_speed(base, hw_engine->base.original_speed);

	/* Release I2C */
	REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1);

	/* Reset HW engine */
	{
		uint32_t i2c_sw_status = 0;
		REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
		/* if used by SW, safe to reset */
		safe_to_reset = (i2c_sw_status == 1);
	}

	if (safe_to_reset)
		REG_UPDATE_2(
			DC_I2C_CONTROL,
			DC_I2C_SOFT_RESET, 1,
			DC_I2C_SW_STATUS_RESET, 1);
	else
		REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);

	/* HW I2c engine - clock gating feature */
	if (!hw_engine->engine_keep_power_up_count)
		disable_i2c_hw_engine(hw_engine);
}
bool dal_i2c_sw_engine_submit_request(
	struct engine *engine,
	struct i2caux_transaction_request *i2caux_request,
	bool middle_of_transaction)
{
	struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);

	struct i2c_engine *base = &sw_engine->base;

	struct i2c_request_transaction_data request;
	bool operation_succeeded = false;

	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
		request.action = middle_of_transaction ?
			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
			I2CAUX_TRANSACTION_ACTION_I2C_READ;
	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
		request.action = middle_of_transaction ?
			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
	else {
		i2caux_request->status =
			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
		/* in DAL2, there was no "return false" */
		return false;
	}

	request.address = (uint8_t)i2caux_request->payload.address;
	request.length = i2caux_request->payload.length;
	request.data = i2caux_request->payload.data;

	base->funcs->submit_channel_request(base, &request);

	if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
		(request.status == I2C_CHANNEL_OPERATION_FAILED))
		i2caux_request->status =
			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
	else {
		enum i2c_channel_operation_result operation_result;

		do {
			operation_result =
				base->funcs->get_channel_status(base, NULL);

			switch (operation_result) {
			case I2C_CHANNEL_OPERATION_SUCCEEDED:
				i2caux_request->status =
					I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
				operation_succeeded = true;
			break;
			case I2C_CHANNEL_OPERATION_NO_RESPONSE:
				i2caux_request->status =
					I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
			break;
			case I2C_CHANNEL_OPERATION_TIMEOUT:
				i2caux_request->status =
				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
			break;
			case I2C_CHANNEL_OPERATION_FAILED:
				i2caux_request->status =
				I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
			break;
			default:
				i2caux_request->status =
				I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
			break;
			}
		} while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
	}

	return operation_succeeded;
}
static void release_engine(
	struct engine *engine)
{
	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);

	struct i2c_engine *base = NULL;
	bool safe_to_reset;
	uint32_t value = 0;

	base = &hw_engine->base.base;

	/* Restore original HW engine speed */

	base->funcs->set_speed(base, hw_engine->base.original_speed);

	/* Release I2C */
	{
		value = dal_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);

		set_reg_field_value(
				value,
				1,
				DC_I2C_ARBITRATION,
				DC_I2C_SW_DONE_USING_I2C_REG);

		dal_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
	}

	/* Reset HW engine */
	{
		uint32_t i2c_sw_status = 0;

		value = dal_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);

		i2c_sw_status = get_reg_field_value(
				value,
				DC_I2C_SW_STATUS,
				DC_I2C_SW_STATUS);
		/* if used by SW, safe to reset */
		safe_to_reset = (i2c_sw_status == 1);
	}
	{
		value = dal_read_reg(engine->ctx, mmDC_I2C_CONTROL);

		if (safe_to_reset)
			set_reg_field_value(
				value,
				1,
				DC_I2C_CONTROL,
				DC_I2C_SOFT_RESET);

		set_reg_field_value(
			value,
			1,
			DC_I2C_CONTROL,
			DC_I2C_SW_STATUS_RESET);

		dal_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
	}

	/* HW I2c engine - clock gating feature */
	if (!hw_engine->engine_keep_power_up_count)
		disable_i2c_hw_engine(hw_engine);
}