* [PATCH v2 0/6] media: synopsys: Add imx93 support
@ 2026-02-13 20:25 Frank Li
2026-02-13 20:25 ` [PATCH v2 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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 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 | 283 +++++++++++++++++++--
2 files changed, 308 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] 13+ messages in thread
* [PATCH v2 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive()
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-13 20:25 ` [PATCH v2 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
` (4 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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] 13+ messages in thread
* [PATCH v2 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all()
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-13 20:25 ` [PATCH v2 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-13 20:25 ` [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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] 13+ messages in thread
* [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-13 20:25 ` [PATCH v2 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
2026-02-13 20:25 ` [PATCH v2 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-16 9:03 ` Michael Riesch
2026-02-13 20:25 ` [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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 v2
- add csi2rx in subject
---
drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 25 ++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index f03fe01280013bf9a832433c6b06dab691bf8f4c..a6d251ca5ad14c5138a6fd0202a970460e64c68f 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -68,6 +68,8 @@ struct dw_mipi_csi2rx_device {
struct v4l2_async_notifier notifier;
struct v4l2_subdev sd;
+ struct v4l2_subdev *remote_source;
+
enum v4l2_mbus_type bus_type;
u32 lanes_num;
};
@@ -429,10 +431,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 media_pad *remote_pad;
+
+ if (!csi2->remote_source)
+ return -ENODEV;
+
+ 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 source pad of %s (%pe)\n",
+ csi2->remote_source->name, remote_pad);
+ return PTR_ERR(remote_pad);
+ }
+ return v4l2_subdev_call(csi2->remote_source, 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,
@@ -485,6 +508,8 @@ static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
return ret;
}
+ csi2->remote_source = sd;
+
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
` (2 preceding siblings ...)
2026-02-13 20:25 ` [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-16 8:11 ` Michael Riesch
2026-02-13 20:25 ` [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
2026-02-13 20:25 ` [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
5 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
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 | 91 ++++++++++++++++++++----
1 file changed, 78 insertions(+), 13 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index a6d251ca5ad14c5138a6fd0202a970460e64c68f..b00ae5fb328da4cc78fe36b629d6661d438e124a 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,33 @@
#define SW_DATATYPE_LS(x) ((x) << 20)
#define SW_DATATYPE_LE(x) ((x) << 26)
+/* Help check wrong access unexisted register at difference IP version */
+#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;
@@ -72,6 +84,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 = {
@@ -186,16 +215,46 @@ 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_is_exist(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_is_exist(csi2, index))
+ writel(val, dw_mipi_csi2rx_get_regaddr(csi2, index));
+
+ dev_err_once(csi2->dev,
+ "write to non-existent register index: %d\n", 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_is_exist(csi2, index))
+ return readl(dw_mipi_csi2rx_get_regaddr(csi2, index));
+
+ dev_err_once(csi2->dev,
+ "read non-existent register index: %d\n", index);
+ /* Return 0 for unexisted registers */
+ return 0;
}
static const struct dw_mipi_csi2rx_format *
@@ -631,6 +690,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,
},
{}
};
@@ -652,6 +712,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] 13+ messages in thread
* [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
` (3 preceding siblings ...)
2026-02-13 20:25 ` [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-16 8:31 ` Michael Riesch
2026-02-13 20:25 ` [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
5 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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>
Signed-off-by: Frank Li <Frank.Li@nxp.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] 13+ messages in thread
* [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
` (4 preceding siblings ...)
2026-02-13 20:25 ` [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
@ 2026-02-13 20:25 ` Frank Li
2026-02-16 8:29 ` Michael Riesch
5 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2026-02-13 20:25 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 included an Image Pixel Interface (IPI), which convert
the received CSI-2 packets, from byte to pixel format, and produces a
pixel data bus containing vertical and horizontal synchronism information.
The reset flow also differs, so add the .assert_reset(), .deassert_reset(),
and .idi_enable() callbacks to support it.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
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 | 163 ++++++++++++++++++++++-
1 file changed, 159 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index b00ae5fb328da4cc78fe36b629d6661d438e124a..ff617a38e8e9ffed4701c15f59aebeca8e4c5553 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -35,6 +35,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,
@@ -44,6 +60,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,
};
@@ -54,8 +80,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 {
@@ -103,6 +134,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,
@@ -319,14 +365,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_is_exist(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)
@@ -334,8 +398,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_is_exist(csi2, DW_MIPI_CSI2RX_MSK1))
+ dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
+
+ if (dw_mipi_csi2rx_is_exist(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 = {
@@ -687,7 +755,94 @@ 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 synopsis 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);
+
+ /*
+ * ndelay is not necessary have MMIO operation, need dummy read to make
+ * sure above write reach target.
+ */
+ 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 make
+ * sure above write reach 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] 13+ messages in thread
* Re: [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets
2026-02-13 20:25 ` [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
@ 2026-02-16 8:11 ` Michael Riesch
0 siblings, 0 replies; 13+ messages in thread
From: Michael Riesch @ 2026-02-16 8:11 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 update.
Some minor nitpicks, but it already looks good.
On 2/13/26 21:25, Frank Li wrote:
> 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.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> 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 | 91 ++++++++++++++++++++----
> 1 file changed, 78 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index a6d251ca5ad14c5138a6fd0202a970460e64c68f..b00ae5fb328da4cc78fe36b629d6661d438e124a 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,33 @@
> #define SW_DATATYPE_LS(x) ((x) << 20)
> #define SW_DATATYPE_LE(x) ((x) << 26)
>
> +/* Help check wrong access unexisted register at difference IP version */
Maybe
/* helper for checking whether register exists */
? However, I think the naming speaks for itself and you can leave the
comment away.
> +#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;
> @@ -72,6 +84,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 = {
> @@ -186,16 +215,46 @@ 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_is_exist(struct dw_mipi_csi2rx_device *csi2,
Sounds a bit weird to me, maybe "dw_mipi_csi2rx_has_reg(ister)" or
"dw_mipi_csi2rx_reg(ister)_exists?
> + 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_is_exist(csi2, index))
> + writel(val, dw_mipi_csi2rx_get_regaddr(csi2, index));
> +
> + dev_err_once(csi2->dev,
> + "write to non-existent register index: %d\n", index);
Not sure about to control flow here, as the error message is shown in
any case. Do you mean
{
if (!dw_mipi_csi2rx_is_exist(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_is_exist(csi2, index))
> + return readl(dw_mipi_csi2rx_get_regaddr(csi2, index));
Here it seems to be correct, but personally I'd prefer
{
if (!dw_mipi_csi2rx_is_exist(csi2, index)) {
// print error
return 0;
}
return readl(...);
}
Anyway, it should match the write method.
> +
> + dev_err_once(csi2->dev,
> + "read non-existent register index: %d\n", index);
> + /* Return 0 for unexisted registers */
/* return 0 for non-existent registers */
or leave away altogether.
> + return 0;
> }
>
> static const struct dw_mipi_csi2rx_format *
> @@ -631,6 +690,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,
> },
> {}
> };
> @@ -652,6 +712,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");
>
With the comments above addressed,
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Best regards,
Michael
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support
2026-02-13 20:25 ` [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
@ 2026-02-16 8:29 ` Michael Riesch
0 siblings, 0 replies; 13+ messages in thread
From: Michael Riesch @ 2026-02-16 8:29 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 update.
On 2/13/26 21:25, Frank Li wrote:
> The i.MX93 uses a newer version of the DW CSI-2 controller with a changed
> register layout and included an Image Pixel Interface (IPI), which convert
and an integrated Image Pixel Interface (IPI), which converts
> the received CSI-2 packets, from byte to pixel format, and produces a
remove both ","
remove extra space between "and" and "produces"
> pixel data bus containing vertical and horizontal synchronism information.
synchronization information?
>
> The reset flow also differs, so add the .assert_reset(), .deassert_reset(),
> and .idi_enable() callbacks to support it.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> 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 | 163 ++++++++++++++++++++++-
> 1 file changed, 159 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index b00ae5fb328da4cc78fe36b629d6661d438e124a..ff617a38e8e9ffed4701c15f59aebeca8e4c5553 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -35,6 +35,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,
> @@ -44,6 +60,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,
> };
> @@ -54,8 +80,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 {
> @@ -103,6 +134,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,
> @@ -319,14 +365,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_is_exist(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)
> @@ -334,8 +398,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_is_exist(csi2, DW_MIPI_CSI2RX_MSK1))
> + dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
> +
> + if (dw_mipi_csi2rx_is_exist(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 = {
> @@ -687,7 +755,94 @@ 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 synopsis DPHY test codes from reset */
Synopsys
> + 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);
> +
> + /*
> + * ndelay is not necessary have MMIO operation, need dummy read to make
> + * sure above write reach target.
/* use read to ensure that the write operation above reaches its target */
?
(Technically it's not a dummy read, as you use the result after the ndelay)
> + */
> + 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 make
> + * sure above write reach target.
> + */
Adjust comment accordingly.
> + 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,
>
With the nitpicks addressed,
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Best regards,
Michael
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string
2026-02-13 20:25 ` [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
@ 2026-02-16 8:31 ` Michael Riesch
2026-02-16 15:22 ` Michael Riesch
0 siblings, 1 reply; 13+ messages in thread
From: Michael Riesch @ 2026-02-16 8:31 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,
Krzysztof Kozlowski
Hi Frank,
On 2/13/26 21:25, Frank Li wrote:
> 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.
RK3568.
>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
With that cosmetic fix,
Acked-by: Michael Riesch <michael.riesch@collabora.com>
Best regards,
Michael
> ---
> .../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>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback
2026-02-13 20:25 ` [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
@ 2026-02-16 9:03 ` Michael Riesch
0 siblings, 0 replies; 13+ messages in thread
From: Michael Riesch @ 2026-02-16 9:03 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,
On 2/13/26 21:25, 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>
> ---
> change in v2
> - add csi2rx in subject
> ---
> drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 25 ++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index f03fe01280013bf9a832433c6b06dab691bf8f4c..a6d251ca5ad14c5138a6fd0202a970460e64c68f 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -68,6 +68,8 @@ struct dw_mipi_csi2rx_device {
> struct v4l2_async_notifier notifier;
> struct v4l2_subdev sd;
>
> + struct v4l2_subdev *remote_source;
> +
> enum v4l2_mbus_type bus_type;
> u32 lanes_num;
> };
> @@ -429,10 +431,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 media_pad *remote_pad;
> +
> + if (!csi2->remote_source)
> + return -ENODEV;
> +
> + 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 source pad of %s (%pe)\n",
> + csi2->remote_source->name, remote_pad);
> + return PTR_ERR(remote_pad);
> + }
You can get the remote subdevice with
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
instead of storing it in the device data.
Best regards,
Michael
> + return v4l2_subdev_call(csi2->remote_source, 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,
> @@ -485,6 +508,8 @@ static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
> return ret;
> }
>
> + csi2->remote_source = sd;
> +
> return 0;
> }
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string
2026-02-16 8:31 ` Michael Riesch
@ 2026-02-16 15:22 ` Michael Riesch
2026-02-16 15:52 ` Frank Li
0 siblings, 1 reply; 13+ messages in thread
From: Michael Riesch @ 2026-02-16 15:22 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,
Krzysztof Kozlowski
Hi Frank,
On 2/16/26 09:31, Michael Riesch wrote:
> Hi Frank,
>
> On 2/13/26 21:25, Frank Li wrote:
>> 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.
>
> RK3568.
>
>>
>> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>> Signed-off-by: Frank Li <Frank.Li@nxp.com>
>
> With that cosmetic fix,
>
> Acked-by: Michael Riesch <michael.riesch@collabora.com>
I just recalled a conversation with Heiko we had off-list a while ago,
and back then we kind of decided against a snps binding document and
compatible, since the integration in the respective SoC (family) varies.
Thus, we went for a Rockchip document (which shall be extended with the
RK3588 variant of this block, for example) and thought that any other
variant (e.g., the one of the imx93) could be documented in a separate
document fsl,somethingsomething.
Seeing that interrupts, clocks, and resets are different, I would
recommend that you add a new fsl,... document.
What do you think?
Best regards,
Michael
>
> Best regards,
> Michael
>
>
>> ---
>> .../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>
>>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string
2026-02-16 15:22 ` Michael Riesch
@ 2026-02-16 15:52 ` Frank Li
0 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2026-02-16 15:52 UTC (permalink / raw)
To: Michael Riesch
Cc: Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, linux-media,
linux-kernel, devicetree, linux-arm-kernel, linux-rockchip,
Guoniu Zhou, Laurent Pinchart, imx, Krzysztof Kozlowski
On Mon, Feb 16, 2026 at 04:22:13PM +0100, Michael Riesch wrote:
> Hi Frank,
>
> On 2/16/26 09:31, Michael Riesch wrote:
> > Hi Frank,
> >
> > On 2/13/26 21:25, Frank Li wrote:
> >> 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.
> >
> > RK3568.
> >
> >>
> >> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> >> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> >
> > With that cosmetic fix,
> >
> > Acked-by: Michael Riesch <michael.riesch@collabora.com>
>
> I just recalled a conversation with Heiko we had off-list a while ago,
> and back then we kind of decided against a snps binding document and
> compatible, since the integration in the respective SoC (family) varies.
> Thus, we went for a Rockchip document (which shall be extended with the
> RK3588 variant of this block, for example) and thought that any other
> variant (e.g., the one of the imx93) could be documented in a separate
> document fsl,somethingsomething.
>
> Seeing that interrupts, clocks, and resets are different, I would
> recommend that you add a new fsl,... document.
>
> What do you think?
It is depend on how much difference. Conside Krzysztof Kozlowski already
acked. we can split it when more soc will be added, if-else branch become
extremly complex and abstract more common property likes dwc usb at that
time.
Frank
>
> Best regards,
> Michael
>
>
> >
> > Best regards,
> > Michael
> >
> >
> >> ---
> >> .../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>
> >>
> >
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-02-16 15:52 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-13 20:25 [PATCH v2 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-13 20:25 ` [PATCH v2 1/6] media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() Frank Li
2026-02-13 20:25 ` [PATCH v2 2/6] media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() Frank Li
2026-02-13 20:25 ` [PATCH v2 3/6] media: synopsys: csi2rx: implement .get_frame_desc() callback Frank Li
2026-02-16 9:03 ` Michael Riesch
2026-02-13 20:25 ` [PATCH v2 4/6] media: synopsys: csi2rx: Use enum and u32 array for register offsets Frank Li
2026-02-16 8:11 ` Michael Riesch
2026-02-13 20:25 ` [PATCH v2 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
2026-02-16 8:31 ` Michael Riesch
2026-02-16 15:22 ` Michael Riesch
2026-02-16 15:52 ` Frank Li
2026-02-13 20:25 ` [PATCH v2 6/6] media: synopsys: csi2rx: add i.MX93 support Frank Li
2026-02-16 8:29 ` Michael Riesch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox