summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c32
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/dma.c7
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/hci.h1
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/pio.c2
4 files changed, 39 insertions, 3 deletions
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index 6da5daf18166..0d3ec674878d 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -151,13 +151,39 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
return 0;
}
+/* Bus disable should never fail, so be generous with the timeout */
+#define BUS_DISABLE_TIMEOUT_US (500 * USEC_PER_MSEC)
+
+static int i3c_hci_bus_disable(struct i3c_hci *hci)
+{
+ u32 regval;
+ int ret;
+
+ reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
+
+ /* Ensure controller is disabled */
+ ret = readx_poll_timeout(reg_read, HC_CONTROL, regval,
+ !(regval & HC_CONTROL_BUS_ENABLE), 0, BUS_DISABLE_TIMEOUT_US);
+ if (ret)
+ dev_err(&hci->master.dev, "%s: Failed to disable bus\n", __func__);
+
+ return ret;
+}
+
+void i3c_hci_sync_irq_inactive(struct i3c_hci *hci)
+{
+ struct platform_device *pdev = to_platform_device(hci->master.dev.parent);
+ int irq = platform_get_irq(pdev, 0);
+
+ reg_write(INTR_SIGNAL_ENABLE, 0x0);
+ synchronize_irq(irq);
+}
+
static void i3c_hci_bus_cleanup(struct i3c_master_controller *m)
{
struct i3c_hci *hci = to_i3c_hci(m);
- struct platform_device *pdev = to_platform_device(m->dev.parent);
- reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
- synchronize_irq(platform_get_irq(pdev, 0));
+ i3c_hci_bus_disable(hci);
hci->io->cleanup(hci);
if (hci->cmd == &mipi_i3c_hci_cmd_v1)
mipi_i3c_hci_dat_v1.cleanup(hci);
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index 5515ed740ca4..54849aa98fad 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -160,6 +160,13 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
rh_reg_write(INTR_SIGNAL_ENABLE, 0);
rh_reg_write(RING_CONTROL, 0);
+ }
+
+ i3c_hci_sync_irq_inactive(hci);
+
+ for (i = 0; i < rings->total; i++) {
+ rh = &rings->headers[i];
+
rh_reg_write(CR_SETUP, 0);
rh_reg_write(IBI_SETUP, 0);
diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
index 3f88b67bc5cc..fd08b701d094 100644
--- a/drivers/i3c/master/mipi-i3c-hci/hci.h
+++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
@@ -142,5 +142,6 @@ void mipi_i3c_hci_pio_reset(struct i3c_hci *hci);
void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci);
void amd_set_od_pp_timing(struct i3c_hci *hci);
void amd_set_resp_buf_thld(struct i3c_hci *hci);
+void i3c_hci_sync_irq_inactive(struct i3c_hci *hci);
#endif
diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
index 109c6c5d83d6..90dca56fc0c5 100644
--- a/drivers/i3c/master/mipi-i3c-hci/pio.c
+++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
@@ -211,6 +211,8 @@ static void hci_pio_cleanup(struct i3c_hci *hci)
pio_reg_write(INTR_SIGNAL_ENABLE, 0x0);
+ i3c_hci_sync_irq_inactive(hci);
+
if (pio) {
dev_dbg(&hci->master.dev, "status = %#x/%#x",
pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE));