diff options
author | Iwona Winiarska <iwona.winiarska@intel.com> | 2022-01-27 23:09:52 +0300 |
---|---|---|
committer | Iwona Winiarska <iwona.winiarska@intel.com> | 2022-02-08 20:27:14 +0300 |
commit | 8a50351caf7915b7a9cf7d7f8393c19b76dfa363 (patch) | |
tree | 040ea4bad10cee0a91d870539e2f169149d282c6 /drivers/peci | |
parent | 747840ee70ac06bd8e4ebad5d0c0d25009481644 (diff) | |
download | linux-8a50351caf7915b7a9cf7d7f8393c19b76dfa363.tar.xz |
peci: aspeed: Improve workaround for controller hang
When processing PECI transaction, observing any HW state different than
"idle" means that PECI controller won't be able to send PECI commands.
When that occurs, attempting to reinitialize the HW by writing registers
is not enough in some cases, and actual reset needs to be involved.
Fixes: 20b020c06aa9 ("peci: aspeed: add a WA to cover timing negotiation issue")
Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
Diffstat (limited to 'drivers/peci')
-rw-r--r-- | drivers/peci/busses/peci-aspeed.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/peci/busses/peci-aspeed.c b/drivers/peci/busses/peci-aspeed.c index 9dd3686a4228..224a3ae8492c 100644 --- a/drivers/peci/busses/peci-aspeed.c +++ b/drivers/peci/busses/peci-aspeed.c @@ -165,10 +165,29 @@ static void aspeed_peci_init_regs(struct aspeed_peci *priv) static inline int aspeed_peci_check_idle(struct aspeed_peci *priv) { u32 cmd_sts = readl(priv->base + ASPEED_PECI_CMD); + int ret; + + /* + * Under normal circumstances, we expect to be idle here. + * In case there were any errors/timeouts that led to the situation + * where the hardware is not in idle state - we need to reset and + * reinitialize it to avoid potential controller hang. + */ + if (FIELD_GET(ASPEED_PECI_CMD_STS_MASK, cmd_sts)) { + ret = reset_control_assert(priv->rst); + if (ret) { + dev_err(priv->dev, "cannot assert reset control\n"); + return ret; + } + + ret = reset_control_deassert(priv->rst); + if (ret) { + dev_err(priv->dev, "cannot deassert reset control\n"); + return ret; + } - if (FIELD_GET(ASPEED_PECI_CMD_STS_MASK, - cmd_sts) == ASPEED_PECI_CMD_STS_ADDR_T_NEGO) aspeed_peci_init_regs(priv); + } return readl_poll_timeout(priv->base + ASPEED_PECI_CMD, cmd_sts, |