* [PATCH v3 0/6] media: synopsys: Add imx93 support
@ 2026-02-16 19:18 Frank Li
2026-02-16 19:18 ` [PATCH v3 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li,
Krzysztof Kozlowski
This 3rd time try to support DW CSI2RX support for imx93.
1st: Create new dw csi2 driver
https://lore.kernel.org/all/20250701-95_cam-v1-5-c5172bab387b@nxp.com/
2nd: Based on legacy imx6's DW CSI2 constroller.
https://lore.kernel.org/imx/20250821-95_cam-v3-0-c9286fbb34b9@nxp.com/
Now rockchip create a common DW CSI2RX driver at
drivers/media/platform/synopsys/dw-mipi-csi2rx.c
This time base on rockchip's implement.
i.MX93's version is newer than rockchip one. i.MX6's is more similar with
rockchips.
But i.MX6 is too old. So start at i.MX93 firstly even it has bigger
difference.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v3:
- use dw_mipi_csi2rx_has_reg().
- detail change see each patches's change log
- Link to v2: https://lore.kernel.org/r/20260213-imx93-dw-csi2-v2-0-8be6039f44c6@nxp.com
Changes in v2:
- use enum and array map to real register offset.
- Please keep the order:
- #includes
- #defines
- enum and struct definitions
- the rest
- detail change see each patches's change log
- Link to v1: https://lore.kernel.org/r/20260210-imx93-dw-csi2-v1-0-69667bb86bfa@nxp.com
---
Frank Li (6):
media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive()
media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all()
media: synopsys: csi2rx: implement .get_frame_desc() callback
media: synopsys: csi2rx: Use enum and u32 array for register offsets
media: dt-bindings: add NXP i.MX93 compatible string
media: synopsys: csi2rx: add i.MX93 support
.../bindings/media/rockchip,rk3568-mipi-csi2.yaml | 47 +++-
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 278 +++++++++++++++++++--
2 files changed, 303 insertions(+), 22 deletions(-)
---
base-commit: ada3fa02f7a95623b724dfe300fce6f49cc2d75a
change-id: 20260128-imx93-dw-csi2-b472ddcb176a
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive()
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
@ 2026-02-16 19:18 ` Frank Li
2026-02-16 19:18 ` [PATCH v3 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li
The DW MIPI CSI-2 RX is used on different SoCs, not all of which provide a
reset controller. Switch to devm_reset_control_get_optional_exclusive()
to support such platforms.
Reset presence and numbering are validated by the DT binding.
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2
- add csi2rx tags in subject
- add Michael Riesch review-by tag
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 170346ae1a599e43bba9d19476ee4d65124303bd..0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -639,7 +639,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(csi2->phy),
"failed to get MIPI CSI-2 PHY\n");
- csi2->reset = devm_reset_control_get_exclusive(dev, NULL);
+ csi2->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(csi2->reset))
return dev_err_probe(dev, PTR_ERR(csi2->reset),
"failed to get reset\n");
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all()
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-16 19:18 ` [PATCH v3 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
@ 2026-02-16 19:18 ` Frank Li
2026-02-16 19:18 ` [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li
devm_clk_bulk_get_all() returns all clocks described in the DT, which are
already validated by the binding. Do not need enforce an expected clock
count.
Only check for error returns (< 0) to support more SoCs.
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2:
- remove DW_MIPI_CSI2RX_CLKS_MAX
- add Michael Riesch reviewed-by tag
- add csi2rx in subject
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7..f03fe01280013bf9a832433c6b06dab691bf8f4c 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -40,8 +40,6 @@
#define SW_DATATYPE_LS(x) ((x) << 20)
#define SW_DATATYPE_LE(x) ((x) << 26)
-#define DW_MIPI_CSI2RX_CLKS_MAX 1
-
enum {
DW_MIPI_CSI2RX_PAD_SINK,
DW_MIPI_CSI2RX_PAD_SRC,
@@ -630,7 +628,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
return PTR_ERR(csi2->base_addr);
ret = devm_clk_bulk_get_all(dev, &csi2->clks);
- if (ret != DW_MIPI_CSI2RX_CLKS_MAX)
+ if (ret < 0)
return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
csi2->clks_num = ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-16 19:18 ` [PATCH v3 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
2026-02-16 19:18 ` [PATCH v3 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
@ 2026-02-16 19:18 ` Frank Li
2026-02-17 7:48 ` Michael Riesch
2026-02-16 19:18 ` [PATCH v3 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
` (2 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li
Implement the .get_frame_desc() callback to fetch information from the
remote endpoint.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- use media_entity_to_v4l2_subdev()
change in v2
- add csi2rx in subject
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index f03fe01280013bf9a832433c6b06dab691bf8f4c..bcbf109a0bfd040c568c0652e28752c94a1bc30d 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -429,10 +429,31 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
return ret;
}
+static int
+dw_mipi_csi2rx_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_frame_desc *fd)
+{
+ struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
+ struct v4l2_subdev *remote_sd;
+ struct media_pad *remote_pad;
+
+ remote_pad = media_pad_remote_pad_unique(&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
+ if (IS_ERR(remote_pad)) {
+ dev_err(csi2->dev, "can't get remote source pad\n");
+ return PTR_ERR(remote_pad);
+ }
+
+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+ return v4l2_subdev_call(remote_sd, pad, get_frame_desc,
+ remote_pad->index, fd);
+}
+
static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
.enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = dw_mipi_csi2rx_set_fmt,
+ .get_frame_desc = dw_mipi_csi2rx_get_frame_desc,
.set_routing = dw_mipi_csi2rx_set_routing,
.enable_streams = dw_mipi_csi2rx_enable_streams,
.disable_streams = dw_mipi_csi2rx_disable_streams,
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
` (2 preceding siblings ...)
2026-02-16 19:18 ` [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
@ 2026-02-16 19:18 ` Frank Li
2026-02-16 19:18 ` [PATCH v3 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
2026-02-16 19:18 ` [PATCH v3 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
5 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li
Use enum dw_mipi_csi2rx_regs_index together with a u32 array to describe
register offsets. This allows supporting new IP versions with different
register layouts in a structured way.
Add rk3568_regs matching the previous macro definitions and pass it as
driver data during probe.
No functional change intended.
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- use dw_mipi_csi2rx_has_reg()
- fix dw_mipi_csi2rx_(write|read))() control flow.
- remove reduntant comment
- add Michael Riesch <michael.riesch@collabora.com>'s review by tags
change in v2
- change to use enum and u32 array method
- use order
- #includes
- #defines
- enum and struct definitions
- the rest
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 94 ++++++++++++++++++++----
1 file changed, 81 insertions(+), 13 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index bcbf109a0bfd040c568c0652e28752c94a1bc30d..536e5df2b4172256def2e2a35b362cfbddf712fa 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -24,15 +24,6 @@
#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
-#define DW_MIPI_CSI2RX_N_LANES 0x04
-#define DW_MIPI_CSI2RX_RESETN 0x10
-#define DW_MIPI_CSI2RX_PHY_STATE 0x14
-#define DW_MIPI_CSI2RX_ERR1 0x20
-#define DW_MIPI_CSI2RX_ERR2 0x24
-#define DW_MIPI_CSI2RX_MSK1 0x28
-#define DW_MIPI_CSI2RX_MSK2 0x2c
-#define DW_MIPI_CSI2RX_CONTROL 0x40
-
#define SW_CPHY_EN(x) ((x) << 0)
#define SW_DSI_EN(x) ((x) << 4)
#define SW_DATATYPE_FS(x) ((x) << 8)
@@ -40,12 +31,32 @@
#define SW_DATATYPE_LS(x) ((x) << 20)
#define SW_DATATYPE_LE(x) ((x) << 26)
+#define DW_REG_EXIST BIT(31)
+#define DW_REG(x) (DW_REG_EXIST | (x))
+
+enum dw_mipi_csi2rx_regs_index {
+ DW_MIPI_CSI2RX_N_LANES,
+ DW_MIPI_CSI2RX_RESETN,
+ DW_MIPI_CSI2RX_PHY_STATE,
+ DW_MIPI_CSI2RX_ERR1,
+ DW_MIPI_CSI2RX_ERR2,
+ DW_MIPI_CSI2RX_MSK1,
+ DW_MIPI_CSI2RX_MSK2,
+ DW_MIPI_CSI2RX_CONTROL,
+
+ DW_MIPI_CSI2RX_MAX,
+};
+
enum {
DW_MIPI_CSI2RX_PAD_SINK,
DW_MIPI_CSI2RX_PAD_SRC,
DW_MIPI_CSI2RX_PAD_MAX,
};
+struct dw_mipi_csi2rx_drvdata {
+ const u32 *regs;
+};
+
struct dw_mipi_csi2rx_format {
u32 code;
u8 depth;
@@ -70,6 +81,23 @@ struct dw_mipi_csi2rx_device {
enum v4l2_mbus_type bus_type;
u32 lanes_num;
+
+ const struct dw_mipi_csi2rx_drvdata *drvdata;
+};
+
+static const u32 rk3568_regs[DW_MIPI_CSI2RX_MAX] = {
+ [DW_MIPI_CSI2RX_N_LANES] = DW_REG(0x4),
+ [DW_MIPI_CSI2RX_RESETN] = DW_REG(0x10),
+ [DW_MIPI_CSI2RX_PHY_STATE] = DW_REG(0x14),
+ [DW_MIPI_CSI2RX_ERR1] = DW_REG(0x20),
+ [DW_MIPI_CSI2RX_ERR2] = DW_REG(0x24),
+ [DW_MIPI_CSI2RX_MSK1] = DW_REG(0x28),
+ [DW_MIPI_CSI2RX_MSK2] = DW_REG(0x2c),
+ [DW_MIPI_CSI2RX_CONTROL] = DW_REG(0x40),
+};
+
+static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
+ .regs = rk3568_regs,
};
static const struct v4l2_mbus_framefmt default_format = {
@@ -184,16 +212,50 @@ static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
return container_of(sd, struct dw_mipi_csi2rx_device, sd);
}
+static bool dw_mipi_csi2rx_has_reg(struct dw_mipi_csi2rx_device *csi2,
+ enum dw_mipi_csi2rx_regs_index index)
+{
+ if (index < DW_MIPI_CSI2RX_MAX &&
+ (csi2->drvdata->regs[index] & DW_REG_EXIST))
+ return true;
+
+ return false;
+}
+
+static void __iomem *
+dw_mipi_csi2rx_get_regaddr(struct dw_mipi_csi2rx_device *csi2,
+ enum dw_mipi_csi2rx_regs_index index)
+{
+ u32 off = (~DW_REG_EXIST) & csi2->drvdata->regs[index];
+
+ return csi2->base_addr + off;
+}
+
static inline void dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device *csi2,
- unsigned int addr, u32 val)
+ enum dw_mipi_csi2rx_regs_index index,
+ u32 val)
{
- writel(val, csi2->base_addr + addr);
+ if (!dw_mipi_csi2rx_has_reg(csi2, index)) {
+ dev_err_once(csi2->dev,
+ "write to non-existent register index: %d\n",
+ index);
+ return;
+ }
+
+ writel(val, dw_mipi_csi2rx_get_regaddr(csi2, index));
}
static inline u32 dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device *csi2,
- unsigned int addr)
+ enum dw_mipi_csi2rx_regs_index index)
{
- return readl(csi2->base_addr + addr);
+ if (!dw_mipi_csi2rx_has_reg(csi2, index)) {
+ dev_err_once(csi2->dev,
+ "read non-existent register index: %d\n", index);
+ /* return 0 for non-existent registers */
+ return 0;
+ }
+
+ return readl(dw_mipi_csi2rx_get_regaddr(csi2, index));
}
static const struct dw_mipi_csi2rx_format *
@@ -627,6 +689,7 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
{
.compatible = "rockchip,rk3568-mipi-csi2",
+ .data = &rk3568_drvdata,
},
{}
};
@@ -648,6 +711,11 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
if (IS_ERR(csi2->base_addr))
return PTR_ERR(csi2->base_addr);
+ csi2->drvdata = device_get_match_data(dev);
+ if (!csi2->drvdata)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to get driver data\n");
+
ret = devm_clk_bulk_get_all(dev, &csi2->clks);
if (ret < 0)
return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 5/6] media: dt-bindings: add NXP i.MX93 compatible string
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
` (3 preceding siblings ...)
2026-02-16 19:18 ` [PATCH v3 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
@ 2026-02-16 19:18 ` Frank Li
2026-02-16 19:18 ` [PATCH v3 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
5 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li,
Krzysztof Kozlowski
The i.MX93 uses the DW CSI-2 RX controller, which is similar to the
Rockchip RK3568 implementation.
The i.MX93 variant provides one IRQ, two clocks, and no resets. Add the
"fsl,imx93-mipi-csi2" compatible string and keep the same constraints for
RK3568.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Acked-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- use RK3568
- add Acked-by: Michael Riesch <michael.riesch@collabora.com>
---
.../bindings/media/rockchip,rk3568-mipi-csi2.yaml | 47 +++++++++++++++++++++-
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
index 2c2bd87582eb8bfdd13720edd62a5f00dda958ba..4ac4a3b6f406408b9524c795e6cdeb117d3353da 100644
--- a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
@@ -17,6 +17,7 @@ description:
properties:
compatible:
enum:
+ - fsl,imx93-mipi-csi2
- rockchip,rk3568-mipi-csi2
reg:
@@ -26,14 +27,23 @@ properties:
items:
- description: Interrupt that signals changes in CSI2HOST_ERR1.
- description: Interrupt that signals changes in CSI2HOST_ERR2.
+ minItems: 1
interrupt-names:
items:
- const: err1
- const: err2
+ minItems: 1
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: per
+ - const: pixel
+ minItems: 1
phys:
maxItems: 1
@@ -88,10 +98,43 @@ required:
- phys
- ports
- power-domains
- - resets
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3568-mipi-csi2
+ then:
+ properties:
+ interrupts:
+ minItems: 2
+ interrupt-names:
+ minItems: 2
+ clocks:
+ maxItems: 1
+ clock-names:
+ maxItems: 1
+ required:
+ - resets
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: fsl,imx93-mipi-csi2
+ then:
+ properties:
+ interrupts:
+ maxItems: 1
+ interrupt-names: false
+ clocks:
+ minItems: 2
+ clock-names:
+ minItems: 2
+
examples:
- |
#include <dt-bindings/clock/rk3568-cru.h>
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 6/6] media: synopsys: csi2rx: add i.MX93 support
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
` (4 preceding siblings ...)
2026-02-16 19:18 ` [PATCH v3 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
@ 2026-02-16 19:18 ` Frank Li
5 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-02-16 19:18 UTC (permalink / raw)
To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li
The i.MX93 uses a newer version of the DW CSI-2 controller with a changed
register layout and an integrated Image Pixel Interface (IPI), which
converts the received CSI-2 packets from byte to pixel format and produces
a pixel data bus containing vertical and horizontal synchronization
information.
The reset flow also differs, so add the .assert_reset(), .deassert_reset(),
and .idi_enable() callbacks to support it.
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change in v3
- tune commit message according to Micheal's feedback.
- Add Micheal's review tags
- remove first comment about read before ndelay() because it use read value.
- but second read() before ndelay() is dummy read().
change in v2
- move macro define to header
- use new register access method
- Keep check register exist to avoid print error message. keep slicence to
access unexisting register may hide problem.
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 159 ++++++++++++++++++++++-
1 file changed, 155 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 536e5df2b4172256def2e2a35b362cfbddf712fa..036f9c7a1b68360dcb5744018d385d4b1a15d506 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -34,6 +34,22 @@
#define DW_REG_EXIST BIT(31)
#define DW_REG(x) (DW_REG_EXIST | (x))
+#define DPHY_TEST_CTRL0_TEST_CLR BIT(0)
+
+#define IPI_VCID_VC(x) FIELD_PREP(GENMASK(1, 0), (x))
+#define IPI_VCID_VC_0_1(x) FIELD_PREP(GENMASK(3, 2), (x))
+#define IPI_VCID_VC_2 BIT(4)
+
+#define IPI_DATA_TYPE_DT(x) FIELD_PREP(GENMASK(5, 0), (x))
+#define IPI_DATA_TYPE_EMB_DATA_EN BIT(8)
+
+#define IPI_MODE_CONTROLLER BIT(1)
+#define IPI_MODE_COLOR_MODE16 BIT(8)
+#define IPI_MODE_CUT_THROUGH BIT(16)
+#define IPI_MODE_ENABLE BIT(24)
+
+#define IPI_MEM_FLUSH_AUTO BIT(8)
+
enum dw_mipi_csi2rx_regs_index {
DW_MIPI_CSI2RX_N_LANES,
DW_MIPI_CSI2RX_RESETN,
@@ -43,6 +59,16 @@ enum dw_mipi_csi2rx_regs_index {
DW_MIPI_CSI2RX_MSK1,
DW_MIPI_CSI2RX_MSK2,
DW_MIPI_CSI2RX_CONTROL,
+ /* imx93 (v150) new register */
+ DW_MIPI_CSI2RX_DPHY_RSTZ,
+ DW_MIPI_CSI2RX_PHY_TST_CTRL0,
+ DW_MIPI_CSI2RX_PHY_TST_CTRL1,
+ DW_MIPI_CSI2RX_PHY_SHUTDOWNZ,
+ DW_MIPI_CSI2RX_IPI_DATATYPE,
+ DW_MIPI_CSI2RX_IPI_MEM_FLUSH,
+ DW_MIPI_CSI2RX_IPI_MODE,
+ DW_MIPI_CSI2RX_IPI_SOFTRSTN,
+ DW_MIPI_CSI2RX_IPI_VCID,
DW_MIPI_CSI2RX_MAX,
};
@@ -53,8 +79,13 @@ enum {
DW_MIPI_CSI2RX_PAD_MAX,
};
+struct dw_mipi_csi2rx_device;
+
struct dw_mipi_csi2rx_drvdata {
const u32 *regs;
+ 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);
};
struct dw_mipi_csi2rx_format {
@@ -100,6 +131,21 @@ static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
.regs = rk3568_regs,
};
+static const u32 imx93_regs[DW_MIPI_CSI2RX_MAX] = {
+ [DW_MIPI_CSI2RX_N_LANES] = DW_REG(0x4),
+ [DW_MIPI_CSI2RX_RESETN] = DW_REG(0x8),
+ [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_TST_CTRL0] = DW_REG(0x50),
+ [DW_MIPI_CSI2RX_PHY_TST_CTRL1] = DW_REG(0x54),
+ [DW_MIPI_CSI2RX_IPI_MODE] = DW_REG(0x80),
+ [DW_MIPI_CSI2RX_IPI_VCID] = DW_REG(0x84),
+ [DW_MIPI_CSI2RX_IPI_DATATYPE] = DW_REG(0x88),
+ [DW_MIPI_CSI2RX_IPI_MEM_FLUSH] = DW_REG(0x8c),
+ [DW_MIPI_CSI2RX_IPI_SOFTRSTN] = DW_REG(0xa0),
+};
+
static const struct v4l2_mbus_framefmt default_format = {
.width = 3840,
.height = 2160,
@@ -320,14 +366,32 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
return -EINVAL;
}
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
+
+ if (csi2->drvdata->dphy_assert_reset)
+ csi2->drvdata->dphy_assert_reset(csi2);
+
control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_N_LANES, lanes - 1);
- dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
+
+ if (dw_mipi_csi2rx_has_reg(csi2, DW_MIPI_CSI2RX_CONTROL))
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
+
+ ret = phy_power_on(csi2->phy);
+ if (ret)
+ return ret;
+
+ if (csi2->drvdata->dphy_deassert_reset)
+ csi2->drvdata->dphy_deassert_reset(csi2);
+
dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 1);
- return phy_power_on(csi2->phy);
+ if (csi2->drvdata->ipi_enable)
+ csi2->drvdata->ipi_enable(csi2);
+
+ return 0;
}
static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
@@ -335,8 +399,12 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
phy_power_off(csi2->phy);
dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
- dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
- dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
+
+ if (dw_mipi_csi2rx_has_reg(csi2, DW_MIPI_CSI2RX_MSK1))
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
+
+ if (dw_mipi_csi2rx_has_reg(csi2, DW_MIPI_CSI2RX_MSK2))
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
}
static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
@@ -686,7 +754,90 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
v4l2_async_nf_cleanup(&csi2->notifier);
}
+static void imx93_csi2rx_dphy_assert_reset(struct dw_mipi_csi2rx_device *csi2)
+{
+ u32 val;
+
+ /* Release Synopsys DPHY test codes from reset */
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_DPHY_RSTZ, 0);
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_PHY_SHUTDOWNZ, 0);
+
+ val = dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_PHY_TST_CTRL0);
+ val &= ~DPHY_TEST_CTRL0_TEST_CLR;
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_PHY_TST_CTRL0, val);
+
+ val = dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_PHY_TST_CTRL0);
+ /* Wait for at least 15ns */
+ ndelay(15);
+ val |= DPHY_TEST_CTRL0_TEST_CLR;
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_PHY_TST_CTRL0, val);
+}
+
+static void imx93_csi2rx_dphy_deassert_reset(struct dw_mipi_csi2rx_device *csi2)
+{
+ /* Release PHY from reset */
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_PHY_SHUTDOWNZ, 0x1);
+ /*
+ * ndelay() is not necessary have MMIO operation, need dummy read to
+ * ensure that the write operation above reaches its target.
+ */
+ dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_PHY_SHUTDOWNZ);
+ ndelay(5);
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_DPHY_RSTZ, 0x1);
+
+ dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_DPHY_RSTZ);
+ ndelay(5);
+}
+
+static void imx93_csi2rx_dphy_ipi_enable(struct dw_mipi_csi2rx_device *csi2)
+{
+ int dt = csi2->formats->csi_dt;
+ u32 val;
+
+ /* Do IPI soft reset */
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_SOFTRSTN, 0x0);
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_SOFTRSTN, 0x1);
+
+ /* Select virtual channel and data type to be processed by IPI */
+ val = IPI_DATA_TYPE_DT(dt);
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_DATATYPE, val);
+
+ /* Set virtual channel 0 as default */
+ val = IPI_VCID_VC(0);
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_VCID, val);
+
+ /*
+ * Select IPI camera timing mode and allow the pixel stream
+ * to be non-continuous when pixel interface FIFO is empty
+ */
+ val = dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_IPI_MODE);
+ val &= ~IPI_MODE_CONTROLLER;
+ val &= ~IPI_MODE_COLOR_MODE16;
+ val |= IPI_MODE_CUT_THROUGH;
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_MODE, val);
+
+ /* Memory is automatically flushed at each Frame Start */
+ val = IPI_MEM_FLUSH_AUTO;
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_MEM_FLUSH, val);
+
+ /* Enable IPI */
+ val = dw_mipi_csi2rx_read(csi2, DW_MIPI_CSI2RX_IPI_MODE);
+ val |= IPI_MODE_ENABLE;
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_MODE, val);
+}
+
+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,
+};
+
static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
+ {
+ .compatible = "fsl,imx93-mipi-csi2",
+ .data = &imx93_drvdata,
+ },
{
.compatible = "rockchip,rk3568-mipi-csi2",
.data = &rk3568_drvdata,
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback
2026-02-16 19:18 ` [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
@ 2026-02-17 7:48 ` Michael Riesch
0 siblings, 0 replies; 8+ messages in thread
From: Michael Riesch @ 2026-02-17 7:48 UTC (permalink / raw)
To: Frank Li, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx
Hi Frank,
Thanks for the patch.
On 2/16/26 20:18, Frank Li wrote:
> Implement the .get_frame_desc() callback to fetch information from the
> remote endpoint.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Best regards,
Michael
> ---
> change in v3
> - use media_entity_to_v4l2_subdev()
>
> change in v2
> - add csi2rx in subject
> ---
> drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index f03fe01280013bf9a832433c6b06dab691bf8f4c..bcbf109a0bfd040c568c0652e28752c94a1bc30d 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -429,10 +429,31 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
> return ret;
> }
>
> +static int
> +dw_mipi_csi2rx_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> + struct v4l2_mbus_frame_desc *fd)
> +{
> + struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
> + struct v4l2_subdev *remote_sd;
> + struct media_pad *remote_pad;
> +
> + remote_pad = media_pad_remote_pad_unique(&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
> + if (IS_ERR(remote_pad)) {
> + dev_err(csi2->dev, "can't get remote source pad\n");
> + return PTR_ERR(remote_pad);
> + }
> +
> + remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
> +
> + return v4l2_subdev_call(remote_sd, pad, get_frame_desc,
> + remote_pad->index, fd);
> +}
> +
> static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
> .enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
> .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = dw_mipi_csi2rx_set_fmt,
> + .get_frame_desc = dw_mipi_csi2rx_get_frame_desc,
> .set_routing = dw_mipi_csi2rx_set_routing,
> .enable_streams = dw_mipi_csi2rx_enable_streams,
> .disable_streams = dw_mipi_csi2rx_disable_streams,
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-02-17 7:48 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-16 19:18 [PATCH v3 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-16 19:18 ` [PATCH v3 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
2026-02-16 19:18 ` [PATCH v3 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
2026-02-16 19:18 ` [PATCH v3 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
2026-02-17 7:48 ` Michael Riesch
2026-02-16 19:18 ` [PATCH v3 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
2026-02-16 19:18 ` [PATCH v3 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
2026-02-16 19:18 ` [PATCH v3 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox