[PATCH v4 4/6] media: synopsys: Add PHY stopstate wait for i.MX93

G.N. Zhou (OSS) guoniu.zhou at oss.nxp.com
Thu May 21 02:29:39 PDT 2026


Hi Alexander,

> -----Original Message-----
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> Sent: Wednesday, May 20, 2026 7:12 PM
> To: Michael Riesch <michael.riesch at collabora.com>; Mauro Carvalho Chehab
> <mchehab at kernel.org>; Rob Herring <robh at kernel.org>; Krzysztof Kozlowski
> <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Heiko Stuebner
> <heiko at sntech.de>; Laurent Pinchart <laurent.pinchart at ideasonboard.com>;
> Frank Li <frank.li at nxp.com>; Sakari Ailus <sakari.ailus at linux.intel.com>; Bryan
> O'Donoghue <bryan.odonoghue at linaro.org>; Mehdi Djait
> <mehdi.djait at linux.intel.com>; Hans Verkuil <hverkuil+cisco at kernel.org>;
> G.N. Zhou (OSS) <guoniu.zhou at oss.nxp.com>
> Cc: linux-media at vger.kernel.org; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; imx at lists.linux.dev; linux-arm-
> kernel at lists.infradead.org; linux-rockchip at lists.infradead.org; G.N. Zhou (OSS)
> <guoniu.zhou at oss.nxp.com>
> Subject: Re: [PATCH v4 4/6] media: synopsys: Add PHY stopstate wait for
> i.MX93
> 
> Hi,
> 
> Am Dienstag, 19. Mai 2026, 04:07:41 CEST schrieb Guoniu Zhou:
> > Implement waiting for D-PHY lanes to enter stop state on i.MX93. This
> > ensures proper PHY initialization by verifying that the clock lane and
> > all active data lanes have entered the stop state before proceeding
> > with further operations.
> >
> > Reviewed-by: Frank Li <Frank.Li at nxp.com>
> > Signed-off-by: Guoniu Zhou <guoniu.zhou at oss.nxp.com>
> > ---
> > Changes in v2:
> > - Removes redundant register availability check
> > - Uses read_poll_timeout() with dw_mipi_csi2rx_read() instead of
> >   readl_poll_timeout() with direct register address
> > - Fixes stopstate condition logic
> > - Check PHY stopstate after sensor enable instead of before to ensure
> >   correct timing.
> > - Optimize PHY stopstate polling parameters (1000us->10us, 2s->1ms) to
> >   balance performance and responsiveness.
> > ---
> >  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 36
> > ++++++++++++++++++++++++
> >  1 file changed, 36 insertions(+)
> >
> > diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > index 92178a3dec5d..8a34aec550ad 100644
> > --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > @@ -11,6 +11,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/phy/phy.h>
> > @@ -35,6 +36,8 @@
> >  #define DW_REG_EXIST		BIT(31)
> >  #define DW_REG(x)		(DW_REG_EXIST | (x))
> >
> > +#define DPHY_STOPSTATE_CLK_LANE		BIT(16)
> > +
> >  #define DPHY_TEST_CTRL0_TEST_CLR	BIT(0)
> >
> >  #define IPI_VCID_VC(x)			FIELD_PREP(GENMASK(1, 0),
> (x))
> > @@ -65,6 +68,7 @@ enum dw_mipi_csi2rx_regs_index {
> >  	DW_MIPI_CSI2RX_PHY_TST_CTRL0,
> >  	DW_MIPI_CSI2RX_PHY_TST_CTRL1,
> >  	DW_MIPI_CSI2RX_PHY_SHUTDOWNZ,
> > +	DW_MIPI_CSI2RX_PHY_STOPSTATE,
> >  	DW_MIPI_CSI2RX_IPI_DATATYPE,
> >  	DW_MIPI_CSI2RX_IPI_MEM_FLUSH,
> >  	DW_MIPI_CSI2RX_IPI_MODE,
> > @@ -87,6 +91,7 @@ struct dw_mipi_csi2rx_drvdata {
> >  	void (*dphy_assert_reset)(struct dw_mipi_csi2rx_device *csi2);
> >  	void (*dphy_deassert_reset)(struct dw_mipi_csi2rx_device *csi2);
> >  	void (*ipi_enable)(struct dw_mipi_csi2rx_device *csi2);
> > +	int (*wait_for_phy_stopstate)(struct dw_mipi_csi2rx_device *csi2);
> >  };
> >
> >  struct dw_mipi_csi2rx_format {
> > @@ -139,6 +144,7 @@ static const u32 imx93_regs[DW_MIPI_CSI2RX_MAX]
> = {
> >  	[DW_MIPI_CSI2RX_PHY_SHUTDOWNZ] = DW_REG(0x40),
> >  	[DW_MIPI_CSI2RX_DPHY_RSTZ] = DW_REG(0x44),
> >  	[DW_MIPI_CSI2RX_PHY_STATE] = DW_REG(0x48),
> > +	[DW_MIPI_CSI2RX_PHY_STOPSTATE] = DW_REG(0x4c),
> >  	[DW_MIPI_CSI2RX_PHY_TST_CTRL0] = DW_REG(0x50),
> >  	[DW_MIPI_CSI2RX_PHY_TST_CTRL1] = DW_REG(0x54),
> >  	[DW_MIPI_CSI2RX_IPI_MODE] = DW_REG(0x80), @@ -556,10 +562,19
> @@
> > static int dw_mipi_csi2rx_enable_streams(struct v4l2_subdev *sd,
> >  	if (ret)
> >  		goto err_csi_stop;
> >
> > +	if (!csi2->enabled_streams &&
> > +	    csi2->drvdata->wait_for_phy_stopstate) {
> > +		ret = csi2->drvdata->wait_for_phy_stopstate(csi2);
> > +		if (ret)
> > +			goto err_disable_streams;
> > +	}
> > +
> >  	csi2->enabled_streams |= streams_mask;
> >
> >  	return 0;
> >
> > +err_disable_streams:
> > +	v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
> >  err_csi_stop:
> >  	/* Stop CSI hardware if no streams are enabled */
> >  	if (!csi2->enabled_streams)
> > @@ -871,11 +886,32 @@ static void imx93_csi2rx_dphy_ipi_enable(struct
> dw_mipi_csi2rx_device *csi2)
> >  	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_MODE, val);  }
> >
> > +static int imx93_csi2rx_wait_for_phy_stopstate(struct
> > +dw_mipi_csi2rx_device *csi2) {
> > +	struct device *dev = csi2->dev;
> > +	u32 stopstate_mask;
> > +	u32 val;
> > +	int ret;
> > +
> > +	stopstate_mask = DPHY_STOPSTATE_CLK_LANE | GENMASK(csi2-
> >lanes_num -
> > +1, 0);
> > +
> > +	ret = read_poll_timeout(dw_mipi_csi2rx_read, val,
> > +				(val & stopstate_mask) == stopstate_mask,
> > +				 10, 1000, true,
> > +				 csi2, DW_MIPI_CSI2RX_PHY_STOPSTATE);
> > +	if (ret)
> > +		dev_err(dev, "lanes are not in stop state: %#x,
> expected %#x\n",
> > +			val, stopstate_mask);
> 
> Did you actually test this on imx93? I'm trying to get my imx327 sensor to run,
> but only run into this error message:
> dw-mipi-csi2rx 4ae00000.mipi-csi: lanes are not in stop state: 0x0, expected
> 0x10003

Thanks for testing. Regarding the lane stop state error on i.MX93 with imx327:

This error indicates the CSI-2 lanes are not in LP-11 (stop) state when 
expected. Please check:

1) Verify the sensor PHY is in LP-11 state before returning from the sensor's 
   s_stream(1) call. The CSI-2 receiver expects lanes to be in stop state 
   initially.

2) Check if the imx327 driver has a delay between starting the stream and 
   returning from s_stream(). If the sensor transitions PHY out of LP-11 
   state during this delay, the CSI driver's lane state check will fail 
   when it runs later. The sensor should remain in LP-11 until the CSI 
   controller completes its initialization.

You may need to remove any delays in the imx327 s_stream implementation, or 
ensure the sensor stays in LP-11 state until the CSI receiver is ready.

If possible, could you share the imx327 driver code or check its s_stream implementation?

Best Regards
G.N Zhou

> 
> Currently I'm using this DT node:
> --8<--
> mipi_csi: mipi-csi at 4ae00000 {
> 	compatible = "fsl,imx93-mipi-csi2";
> 	reg = <0x4ae00000 0x10000>;
> 	interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
> 	clocks = <&clk IMX93_CLK_MIPI_CSI_GATE>,
> 			<&clk IMX93_CLK_CAM_PIX>;
> 	clock-names = "per", "pixel";
> 	assigned-clocks = <&clk IMX93_CLK_CAM_PIX>;
> 	assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
> 	assigned-clock-rates = <140000000>;
> 	power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_CSI>;
> 	phys = <&dphy_rx>;
> 	phy-names = "dphy-rx";
> 	status = "disabled";
> 
> 	ports {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 
> 		port at 0 {
> 			reg = <0>;
> 
> 			mipi_from_sensor: endpoint {
> 				data-lanes = <1 2>;
> 				bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
> 			};
> 		};
> 
> 		port at 1 {
> 			reg = <1>;
> 
> 			mipi_to_isi: endpoint {
> 				remote-endpoint = <&isi_in>;
> 			};
> 		};
> 	};
> };
> --8<--
> 
> Am I'm missing something?
> 
> best regards,
> Alexander
> 
> > +
> > +	return ret;
> > +}
> > +
> >  static const struct dw_mipi_csi2rx_drvdata imx93_drvdata = {
> >  	.regs = imx93_regs,
> >  	.dphy_assert_reset = imx93_csi2rx_dphy_assert_reset,
> >  	.dphy_deassert_reset = imx93_csi2rx_dphy_deassert_reset,
> >  	.ipi_enable = imx93_csi2rx_dphy_ipi_enable,
> > +	.wait_for_phy_stopstate = imx93_csi2rx_wait_for_phy_stopstate,
> >  };
> >
> >  static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
> >
> >
> 
> 
> --
> TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
> Amtsgericht München, HRB 105018
> Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
> http://www.tq-group.com/
> 




More information about the Linux-rockchip mailing list