@@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
@@ -41,8 +42,12 @@
#define CSI2RX_STREAM_CTRL_REG(n) (CSI2RX_STREAM_BASE(n) + 0x000)
#define CSI2RX_STREAM_CTRL_SOFT_RST BIT(4)
+#define CSI2RX_STREAM_CTRL_STOP BIT(1)
#define CSI2RX_STREAM_CTRL_START BIT(0)
+#define CSI2RX_STREAM_STATUS_REG(n) (CSI2RX_STREAM_BASE(n) + 0x004)
+#define CSI2RX_STREAM_STATUS_RDY BIT(31)
+
#define CSI2RX_STREAM_DATA_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x008)
#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT BIT(31)
#define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n) BIT((n) + 16)
@@ -310,13 +315,25 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
static void csi2rx_stop(struct csi2rx_priv *csi2rx)
{
unsigned int i;
+ u32 val;
+ int ret;
clk_prepare_enable(csi2rx->p_clk);
reset_control_assert(csi2rx->sys_rst);
clk_disable_unprepare(csi2rx->sys_clk);
for (i = 0; i < csi2rx->max_streams; i++) {
- writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+ writel(CSI2RX_STREAM_CTRL_STOP,
+ csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+
+ ret = readl_relaxed_poll_timeout(csi2rx->base +
+ CSI2RX_STREAM_STATUS_REG(i),
+ val,
+ !(val & CSI2RX_STREAM_STATUS_RDY),
+ 10, 10000);
+ if (ret)
+ dev_warn(csi2rx->dev,
+ "Failed to stop streaming on pad%u\n", i);
reset_control_assert(csi2rx->pixel_rst[i]);
clk_disable_unprepare(csi2rx->pixel_clk[i]);