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 <pmarheine@chromium.org>
Signed-off-by: Jun Lin <CHLin56@nuvoton.com>
This commit is contained in:
Peter Marheine 2022-05-18 16:43:51 +10:00 committed by Carles Cufí
commit 95fb984f0b

View file

@ -3,6 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/pm/policy.h>
#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;
}