[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