summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2024-12-31 13:59:03 +0200
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2025-01-12 23:54:39 +0100
commitccdb2e0e3b00d13df90ac7a0524dd855173f1171 (patch)
tree113bb3b70252f118f7574a9c4ab1289eb9f98439
parent0d2c022ffa7ccbd5bed5b18eefbda7ef2df4f81f (diff)
downloadlinux-ccdb2e0e3b00d13df90ac7a0524dd855173f1171.tar.gz
linux-ccdb2e0e3b00d13df90ac7a0524dd855173f1171.tar.bz2
linux-ccdb2e0e3b00d13df90ac7a0524dd855173f1171.zip
i3c: mipi-i3c-hci: Add Intel specific quirk to ring resuming
MIPI I3C HCI on Intel hardware requires a quirk where ring needs to stop and set to run again after resuming the halted controller. This is not expected from the MIPI I3C HCI specification and is Intel specific. Add this quirk to generic aborted transfer handling and execute it only when ring is not in running state after a transfer error and attempted controller resume. This is the case on Intel hardware. It is not fully clear to me what is the ring running state in generic hardware in such case. I would expect if ring is not running, then stop request is a no-op and run request is either required or does the same what controller resume would do. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Link: https://lore.kernel.org/r/20241231115904.620052-1-jarkko.nikula@linux.intel.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/dma.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index e8e56a8d2057..491dfe70b660 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -758,9 +758,26 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci)
complete(&rh->op_done);
if (status & INTR_TRANSFER_ABORT) {
+ u32 ring_status;
+
dev_notice_ratelimited(&hci->master.dev,
"ring %d: Transfer Aborted\n", i);
mipi_i3c_hci_resume(hci);
+ ring_status = rh_reg_read(RING_STATUS);
+ if (!(ring_status & RING_STATUS_RUNNING) &&
+ status & INTR_TRANSFER_COMPLETION &&
+ status & INTR_TRANSFER_ERR) {
+ /*
+ * Ring stop followed by run is an Intel
+ * specific required quirk after resuming the
+ * halted controller. Do it only when the ring
+ * is not in running state after a transfer
+ * error.
+ */
+ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE);
+ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE |
+ RING_CTRL_RUN_STOP);
+ }
}
if (status & INTR_WARN_INS_STOP_MODE)
dev_warn_ratelimited(&hci->master.dev,