Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions drivers/i3c/master/mipi-i3c-hci/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/errno.h>
#include <linux/i3c/master.h>
#include <linux/io.h>
#include <linux/iopoll.h>

#include "hci.h"
#include "cmd.h"
Expand Down Expand Up @@ -859,6 +860,39 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
rh_reg_write(CHUNK_CONTROL, rh_reg_read(CHUNK_CONTROL) + ibi_chunks);
}

#ifdef CONFIG_ARCH_ASPEED
/*
* The ASPEED I3C controller reuses the PIO FIFO in DMA mode. On transfer error or abort, poll the
* DMA debug busy bit to ensure all transfers are complete before resetting the FIFO, as the
* interrupt will be raised before the DMA engine completes the transfer.
*/
static void aspeed_pio_fifo_reset(struct i3c_hci *hci)
{
u32 wdma_dbg, rdma_dbg;
int ret;

dev_dbg(&hci->master.dev, "WDMA_DBG_LO = 0x%x, RDMA_DBG_LO = 0x%x RING_STATUS = 0x%x\n",
readl(hci->base_regs + ASPEED_I3C_WDMA_DBG_LO),
readl(hci->base_regs + ASPEED_I3C_RDMA_DBG_LO),
readl(hci->base_regs + ASPEED_I3C_RING_STATUS));

/* Poll I3C_DMA_DBG_LO_BUSY until it becomes 0 */
ret = readl_poll_timeout_atomic(hci->base_regs + ASPEED_I3C_WDMA_DBG_LO, wdma_dbg,
!(wdma_dbg & I3C_DMA_DBG_LO_BUSY), 1, 100000);
if (ret)
dev_warn(&hci->master.dev, "WDMA still busy after timeout: 0x%x\n", wdma_dbg);

ret = readl_poll_timeout_atomic(hci->base_regs + ASPEED_I3C_RDMA_DBG_LO, rdma_dbg,
!(rdma_dbg & I3C_DMA_DBG_LO_BUSY), 1, 100000);
if (ret)
dev_warn(&hci->master.dev, "RDMA still busy after timeout: 0x%x\n", rdma_dbg);

mipi_i3c_hci_pio_ibi_reset(hci);
mipi_i3c_hci_pio_reset(hci);
}

#endif

static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
{
struct hci_rings_data *rings = hci->io_data;
Expand Down Expand Up @@ -887,6 +921,9 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
if (unlikely(status & INTR_TRANSFER_ERR)) {
dev_warn(&hci->master.dev,
"ring %d: Transfer Error\n", i);
#ifdef CONFIG_ARCH_ASPEED
aspeed_pio_fifo_reset(hci);
#endif
mipi_i3c_hci_resume(hci);
}
}
Expand All @@ -897,12 +934,7 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
dev_notice_ratelimited(&hci->master.dev,
"ring %d: Transfer Aborted\n", i);
#ifdef CONFIG_ARCH_ASPEED
/*
* Aspeed i3c controller will reuse the PIO fifo in DMA mode,
* so we need to reset the PIO fifo when the transfer is aborted.
*/
mipi_i3c_hci_pio_ibi_reset(hci);
mipi_i3c_hci_pio_reset(hci);
aspeed_pio_fifo_reset(hci);
#endif
mipi_i3c_hci_resume(hci);
}
Expand Down
30 changes: 30 additions & 0 deletions drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,36 @@
#define ASPEED_I3C_AUTOCMD_SEL_112_119 0x78
#define ASPEED_I3C_AUTOCMD_SEL_120_127 0x7C

#define ASPEED_I3C_WDMA_CTRL 0x80
#define ASPEED_I3C_WDMA_DBG_LO 0x84
#define ASPEED_I3C_WDMA_DBG_HI 0x88
#define ASPEED_I3C_RDMA_CTRL 0x90
#define ASPEED_I3C_RDMA_DBG_LO 0x94
#define ASPEED_I3C_RDMA_DBG_HI 0x98
#define I3C_DMA_DBG_LO_ABORT BIT(0)
#define I3C_DMA_DBG_LO_BUSY BIT(1)
#define I3C_DMA_DBG_LO_DONE BIT(2)
#define I3C_DMA_DBG_LO_START BIT(3)
#define I3C_DMA_DBG_LO_READY BIT(4)
#define I3C_DMA_DBG_LO_VALID BIT(5)
#define I3C_DMA_DBG_LO_EN BIT(10)

#define ASPEED_I3C_RING_STATUS 0x9C
#define I3C_RING_IDLE 0
#define I3C_RING_GET_TRANSFER 1
#define I3C_RING_GET_TX_DATA 2
#define I3C_RING_CMD_PROCESS 3
#define I3C_RING_WRITE_RX_DATA 4
#define I3C_RING_WRITE_RESPONSE 5
#define I3C_RING_UPDATE_CR_PTR 6
#define I3C_RING_WRITE_IBI_STS 7
#define I3C_RING_WRITE_IBI_DAT 8
#define I3C_RING_UPDATE_IBI_PTR 9
#define I3C_RING_ABORT 10
#define I3C_RING_SLV_WRITE_DATA 11
#define I3C_RING_SLV_WRITE_RESPONSE 12
#define I3C_RING_SLV_UPDATE_PT 13

#define ASPEED_I3C_SLV_CHAR_CTRL 0xA0
#define ASPEED_I3C_SLV_CHAR_CTRL_DCR GENMASK(23, 16)
#define ASPEED_I3C_SLV_CHAR_CTRL_BCR GENMASK(15, 8)
Expand Down