From 95fb984f0b818fd5c118b72e78201152d3dd6f1f Mon Sep 17 00:00:00 2001 From: Peter Marheine Date: Wed, 18 May 2022 16:43:51 +1000 Subject: [PATCH] driver: i2c: npcx: prevent sleep during I2C transactions Deep Sleep mode stops SMB module clocks which could interrupt ongoing I2C transactions, so have the I2C driver acquire a PM lock at the beginning of a transaction and release it at the end in order to ensure the module remains active. Signed-off-by: Peter Marheine Signed-off-by: Jun Lin --- drivers/i2c/i2c_npcx_controller.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c_npcx_controller.c b/drivers/i2c/i2c_npcx_controller.c index c11a566424e..055ef45d029 100644 --- a/drivers/i2c/i2c_npcx_controller.c +++ b/drivers/i2c/i2c_npcx_controller.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #define DT_DRV_COMPAT nuvoton_npcx_i2c_ctrl @@ -817,6 +818,12 @@ int npcx_i2c_ctrl_transfer(const struct device *i2c_dev, struct i2c_msg *msgs, int ret = 0; uint8_t i; + /* + * suspend-to-idle stops SMB module clocks (derived from APB2/APB3), which must remain + * active during a transaction + */ + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); + /* Does bus need recovery? */ if (data->oper_state != NPCX_I2C_WRITE_SUSPEND && data->oper_state != NPCX_I2C_READ_SUSPEND) { @@ -825,7 +832,7 @@ int npcx_i2c_ctrl_transfer(const struct device *i2c_dev, struct i2c_msg *msgs, ret = i2c_ctrl_recovery(i2c_dev); /* Recovery failed, return it immediately */ if (ret) { - return ret; + goto out; } } } @@ -876,10 +883,12 @@ int npcx_i2c_ctrl_transfer(const struct device *i2c_dev, struct i2c_msg *msgs, * layer still needs to know why the transaction failed. */ if (recovery_error != 0) { - return recovery_error; + ret = recovery_error; } } +out: + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); return ret; }