[PATCH 1/6] media: rockchip: rkcif: mask MIPI interrupts when powered

From: Daniel Golle

Date: Tue Nov 03 2026 - 06:31:30 EST


The MIPI interrupt enable register comes out of every reset with all
27 sources enabled. Of those only the frame end bits are handled, so
the line stays asserted at about a thousand interrupts per second
while the block is powered. The kernel then reports the interrupt as
unhandled and disables it, after which frame completion only happens
from the spurious interrupt poll. The poll can also call the handler
while the block is clock gated.

Clear the enable register and the status bits after the block has been
reset and clocked, and after the reset in runtime suspend. Treat any
status bit that the handler has read and cleared as handled.

Assisted-by: LLM
Signed-off-by: Daniel Golle <daniel@xxxxxxxxxxxxxx>
---
.../rockchip/rkcif/rkcif-capture-mipi.c | 19 +++++++++++++++++++
.../rockchip/rkcif/rkcif-capture-mipi.h | 2 ++
.../media/platform/rockchip/rkcif/rkcif-dev.c | 3 +++
3 files changed, 24 insertions(+)

diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
index bc9518f8db507..686b995525b9b 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c
@@ -810,6 +810,23 @@ static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val);
}

+void rkcif_mipi_irq_mask(struct rkcif_device *rkcif)
+{
+ if (!rkcif->match_data->mipi)
+ return;
+
+ for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
+ struct rkcif_interface *interface =
+ &rkcif->interfaces[RKCIF_MIPI_BASE + i];
+
+ if (!interface->rkcif)
+ continue;
+
+ rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, 0);
+ rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, ~0);
+ }
+}
+
irqreturn_t rkcif_mipi_isr(int irq, void *ctx)
{
struct device *dev = ctx;
@@ -823,6 +840,8 @@ irqreturn_t rkcif_mipi_isr(int irq, void *ctx)

intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat);
+ if (intstat)
+ ret = IRQ_HANDLED;

for (unsigned int j = 0; j < interface->streams_num; j++) {
struct rkcif_stream *stream = &interface->streams[j];
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
index 7edaca44f653c..167b43756929b 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h
@@ -21,4 +21,6 @@ void rkcif_mipi_unregister(struct rkcif_device *rkcif);

irqreturn_t rkcif_mipi_isr(int irq, void *ctx);

+void rkcif_mipi_irq_mask(struct rkcif_device *rkcif);
+
#endif
diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
index be3a174b9aab0..fbc8ed78d99ea 100644
--- a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
+++ b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c
@@ -281,6 +281,7 @@ static int rkcif_runtime_suspend(struct device *dev)
reset_control_assert(rkcif->reset);
udelay(5);
reset_control_deassert(rkcif->reset);
+ rkcif_mipi_irq_mask(rkcif);

clk_bulk_disable_unprepare(rkcif->clks_num, rkcif->clks);

@@ -298,6 +299,8 @@ static int rkcif_runtime_resume(struct device *dev)
return ret;
}

+ rkcif_mipi_irq_mask(rkcif);
+
return 0;
}

--
2.56.0