diff mbox series

[3/3] drivers: fpga: intel_pr: enable illegal request detection

Message ID 20221107133351.26311-3-jit.loon.lim@intel.com
State Needs Review / ACK, archived
Delegated to: Marek Vasut
Headers show
Series [1/3] fpga: intel_pr: Change to use fdt_get_resource() | expand

Commit Message

Jit Loon Lim Nov. 7, 2022, 1:33 p.m. UTC
From: "Chew, Chiau Ee" <chiau.ee.chew@@intel.com>

This is to enable check on the freeze_illegal_request register
whereby high on any bit of this bus indicates a read or write
issue by a static region master when an freeze bridge is in the
freeze state. In the case if any of the bit is high, write 1
to first clear the bit and then return with error.

Signed-off-by: Chew, Chiau Ee <chiau.ee.chew@@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 drivers/fpga/intel_pr.c | 54 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 45 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/drivers/fpga/intel_pr.c b/drivers/fpga/intel_pr.c
index a0a758488b..e84845c918 100644
--- a/drivers/fpga/intel_pr.c
+++ b/drivers/fpga/intel_pr.c
@@ -62,6 +62,49 @@  static int intel_get_freeze_br_addr(fdt_addr_t *addr, unsigned int region)
 	return ret;
 }
 
+static int intel_freeze_br_req_ack(fdt_addr_t addr, u32 req_ack)
+{
+	u32 status, illegal, ctrl;
+	int ret = -ETIMEDOUT;
+	unsigned long start = get_timer(0);
+
+	while (1) {
+		illegal = readl(addr + FREEZE_CSR_ILLEGAL_REQ_OFFSET);
+		if (illegal) {
+			printf("illegal request 0x%08x detected in freeze bridge\n", illegal);
+
+			writel(illegal, addr + FREEZE_CSR_ILLEGAL_REQ_OFFSET);
+
+			illegal = readl(addr + FREEZE_CSR_ILLEGAL_REQ_OFFSET);
+			if (illegal)
+				printf("illegal request 0x%08x detected in freeze bridge are not cleared\n",
+				       illegal);
+
+			ret = -EINVAL;
+			break;
+		}
+
+		status = readl(addr + FREEZE_CSR_STATUS_OFFSET);
+		status &= req_ack;
+		if (status) {
+			ctrl = readl(addr + FREEZE_CSR_CTRL_OFFSET);
+			printf("%s request %x acknowledged %x %x\n",
+			       __func__, req_ack, status, ctrl);
+
+			ret = 0;
+			break;
+		}
+
+		if (get_timer(start) > FREEZE_TIMEOUT)
+			break;
+
+		udelay(1);
+		WATCHDOG_RESET();
+	}
+
+	return ret;
+}
+
 static int intel_freeze_br_do_freeze(unsigned int region)
 {
 	u32 status;
@@ -81,11 +124,7 @@  static int intel_freeze_br_do_freeze(unsigned int region)
 
 	writel(FREEZE_CSR_CTRL_FREEZE_REQ, addr + FREEZE_CSR_CTRL_OFFSET);
 
-	ret = wait_for_bit_le32((const u32 *)(addr +
-				 FREEZE_CSR_STATUS_OFFSET),
-				 FREEZE_CSR_STATUS_FREEZE_REQ_DONE, true,
-				 FREEZE_TIMEOUT, false);
-
+	ret = intel_freeze_br_req_ack(addr, FREEZE_CSR_STATUS_FREEZE_REQ_DONE);
 	if (ret)
 		writel(0, addr + FREEZE_CSR_CTRL_OFFSET);
 	else
@@ -115,10 +154,7 @@  static int intel_freeze_br_do_unfreeze(unsigned int region)
 
 	writel(FREEZE_CSR_CTRL_UNFREEZE_REQ, addr + FREEZE_CSR_CTRL_OFFSET);
 
-	ret = wait_for_bit_le32((const u32 *)(addr +
-				 FREEZE_CSR_STATUS_OFFSET),
-				 FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE, true,
-				 FREEZE_TIMEOUT, false);
+	ret = intel_freeze_br_req_ack(addr, FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE);
 
 	writel(0, addr + FREEZE_CSR_CTRL_OFFSET);