summaryrefslogtreecommitdiff
path: root/drivers/peci
diff options
context:
space:
mode:
authorIwona Winiarska <iwona.winiarska@intel.com>2022-01-27 23:09:52 +0300
committerIwona Winiarska <iwona.winiarska@intel.com>2022-02-08 20:27:14 +0300
commit8a50351caf7915b7a9cf7d7f8393c19b76dfa363 (patch)
tree040ea4bad10cee0a91d870539e2f169149d282c6 /drivers/peci
parent747840ee70ac06bd8e4ebad5d0c0d25009481644 (diff)
downloadlinux-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.c23
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,