Commit 277144f8 authored by Devyn Liu's avatar Devyn Liu Committed by Hao Chen
Browse files

i2c: hisi: Add I2C controller reset and initialization proccess in bus recovery action

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9KYFI


CVE: NA

-----------------------------------------------

The I2C controller hardware manual specifies the bus recovery operation
for I2C. It is recommended to reset the I2C controller and reinitialize
the I2C bus configuration in bus recovery operation, which can more
effectively ensure the recovery of the I2C bus.
So we add I2C controller reset and initialization proccess in bus
recovery action.

Signed-off-by: default avatarDevyn Liu <liudingyuan@huawei.com>
Signed-off-by: default avatarJunhua Lu <lujunhua7@h-partners.com>
parent 3fd47296
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -462,6 +462,26 @@ static void hisi_i2c_configure_bus(struct hisi_i2c_controller *ctlr)

#ifdef CONFIG_ACPI
#define HISI_I2C_PIN_MUX_METHOD	"PMUX"
#define HISI_I2C_SOFT_RESET_METHOD	"SRST"

/**
 * i2c_hisi_soft_reset - Do I2C master soft reset method through ACPI
 * @dev: device need to be reset
 *
 * The function invokes the specific ACPI method "SRST" for trigger a soft
 * reset of I2C controller in order to help on I2C controller recover from
 * the abnormal state after bus recovery process.
 */
static void i2c_hisi_soft_reset(struct device *dev)
{
	acpi_handle handle = ACPI_HANDLE(dev);
	acpi_status status;
	unsigned long long data;

	status = acpi_evaluate_integer(handle, HISI_I2C_SOFT_RESET_METHOD, NULL, &data);
	dev_info(dev, "I2C controller reset %s", ACPI_FAILURE(status) ? "failed" :
		 "succeed");
}

/**
 * i2c_dw_acpi_pin_mux_change - Change the I2C controller's pin mux through ACPI
@@ -499,6 +519,13 @@ static void i2c_hisi_unprepare_recovery(struct i2c_adapter *adap)
	struct hisi_i2c_controller *ctlr = i2c_get_adapdata(adap);

	i2c_hisi_pin_mux_change(ctlr->dev, false);
	i2c_hisi_soft_reset(ctlr->dev);

	/*
	 * After a soft reset, the device configuration return to default
	 * values and require reinitialization.
	 */
	hisi_i2c_configure_bus(ctlr);
}

static void hisi_i2c_init_recovery_info(struct hisi_i2c_controller *ctlr)
@@ -510,7 +537,8 @@ static void hisi_i2c_init_recovery_info(struct hisi_i2c_controller *ctlr)
	if (acpi_disabled)
		return;

	if (!adev || !acpi_has_method(adev->handle, HISI_I2C_PIN_MUX_METHOD))
	if (!adev || !acpi_has_method(adev->handle, HISI_I2C_PIN_MUX_METHOD) ||
	    !acpi_has_method(adev->handle, HISI_I2C_SOFT_RESET_METHOD))
		return;

	gpio = devm_gpiod_get_optional(ctlr->dev, "scl", GPIOD_OUT_HIGH);