Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -4179,7 +4179,6 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=m
CONFIG_I2C_GPIO=m
# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
CONFIG_I2C_HISI=m
# CONFIG_I2C_HISI is not set
CONFIG_I2C_MESON=m
CONFIG_I2C_MV64XXX=m
# CONFIG_I2C_NOMADIK is not set
Expand Down
1 change: 0 additions & 1 deletion config.aarch64-64k
Original file line number Diff line number Diff line change
Expand Up @@ -4177,7 +4177,6 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=m
CONFIG_I2C_GPIO=m
# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
CONFIG_I2C_HISI=m
# CONFIG_I2C_HISI is not set
CONFIG_I2C_MESON=m
CONFIG_I2C_MV64XXX=m
# CONFIG_I2C_NOMADIK is not set
Expand Down
33 changes: 31 additions & 2 deletions drivers/i2c/busses/i2c-hisi.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,29 @@ 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_dw_acpi_pin_mux_change - Change the I2C controller's pin mux through ACPI
* 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_hisi_pin_mux_change - Change the I2C controller's pin mux through ACPI
* @dev: device owns the SCL/SDA pin
* @to_gpio: true to switch to GPIO, false to switch to SCL/SDA
*
Expand Down Expand Up @@ -498,6 +518,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)
Expand All @@ -509,7 +536,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);
Expand Down Expand Up @@ -613,3 +641,4 @@ module_platform_driver(hisi_i2c_driver);
MODULE_AUTHOR("Yicong Yang <yangyicong@hisilicon.com>");
MODULE_DESCRIPTION("HiSilicon I2C Controller Driver");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: gpio-hisi");