[PATCH v4 1/2] arm64: dts: imx8mq-evk: Add OV5640 camera support via overlays

From: robby . cai

Date: Fri Jun 19 2026 - 06:03:35 EST


From: Robby Cai <robby.cai@xxxxxxx>

Add overlays for single and dual camera setups on CSI1 and CSI2, enabling
the following media pipelines:

- OV5640 (I2C2) -> MIPI CSI1 -> CSI1 bridge
- OV5640 (I2C1) -> MIPI CSI2 -> CSI2 bridge

On the i.MX8MQ EVK, both sensors share a common reset GPIO, while each
sensor has an independent powerdown (PWDN) GPIO.

Both sensors also share the same MCLK source (CLKO2), configured
identically as required by the hardware design.

Signed-off-by: Robby Cai <robby.cai@xxxxxxx>
---
arch/arm64/boot/dts/freescale/Makefile | 7 ++
.../dts/freescale/imx8mq-evk-ov5640-csi1.dtso | 69 +++++++++++++++++++
.../dts/freescale/imx8mq-evk-ov5640-csi2.dtso | 65 +++++++++++++++++
arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 50 ++++++++++++++
4 files changed, 191 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 8ddaab127ab9..8507cbdb5556 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -501,6 +501,13 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
imx8mq-evk-pcie1-ep-dtbs += imx8mq-evk.dtb imx-pcie1-ep.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk-pcie1-ep.dtb

+imx8mq-evk-ov5640-csi1-dtbs := imx8mq-evk.dtb imx8mq-evk-ov5640-csi1.dtbo
+dtb-${CONFIG_ARCH_MXC} += imx8mq-evk-ov5640-csi1.dtb
+imx8mq-evk-ov5640-csi2-dtbs := imx8mq-evk.dtb imx8mq-evk-ov5640-csi2.dtbo
+dtb-${CONFIG_ARCH_MXC} += imx8mq-evk-ov5640-csi2.dtb
+imx8mq-evk-ov5640-dual-dtbs := imx8mq-evk.dtb imx8mq-evk-ov5640-csi1.dtbo imx8mq-evk-ov5640-csi2.dtbo
+dtb-${CONFIG_ARCH_MXC} += imx8mq-evk-ov5640-dual.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-kontron-pitx-imx8m.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi1.dtso b/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi1.dtso
new file mode 100644
index 000000000000..1e9931802cdc
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi1.dtso
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2026 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/imx8mq-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/video-interfaces.h>
+
+&csi1 {
+ status = "okay";
+};
+
+&i2c2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ camera@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_camera1_pwdn>;
+ clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ clock-names = "xclk";
+ assigned-clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_200M>;
+ assigned-clock-rates = <20000000>;
+ powerdown-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+ DOVDD-supply = <&sw4_reg>;
+ AVDD-supply = <&reg_2v8>;
+ DVDD-supply = <&reg_1v5>;
+
+ port {
+ camera1_ep: endpoint {
+ remote-endpoint = <&mipi_csi1_in_ep>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+};
+
+&mipi_csi1 {
+ assigned-clock-rates = <266000000>, <200000000>, <66000000>;
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mipi_csi1_in_ep: endpoint {
+ remote-endpoint = <&camera1_ep>;
+ data-lanes = <1 2>;
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi2.dtso b/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi2.dtso
new file mode 100644
index 000000000000..fd247b3b5982
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk-ov5640-csi2.dtso
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2026 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/imx8mq-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/video-interfaces.h>
+
+&csi2 {
+ status = "okay";
+};
+
+&i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_camera2_pwdn>;
+ clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ clock-names = "xclk";
+ assigned-clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_200M>;
+ assigned-clock-rates = <20000000>;
+ powerdown-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+ DOVDD-supply = <&sw4_reg>;
+ AVDD-supply = <&reg_2v8>;
+ DVDD-supply = <&reg_1v5>;
+
+ port {
+ camera2_ep: endpoint {
+ remote-endpoint = <&mipi_csi2_in_ep>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+};
+
+&mipi_csi2 {
+ assigned-clock-rates = <266000000>, <200000000>, <66000000>;
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mipi_csi2_in_ep: endpoint {
+ remote-endpoint = <&camera2_ep>;
+ data-lanes = <1 2>;
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index e7d87ea81b69..d8c139c9128d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -50,6 +50,20 @@ reg_usdhc2_vmmc: regulator-vsd-3v3 {
enable-active-high;
};

+ reg_1v5: regulator-1v5 {
+ compatible = "regulator-fixed";
+ regulator-name = "DVDD_1V5";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ };
+
+ reg_2v8: regulator-2v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AVDD_2V8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
buck2_reg: regulator-buck2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_buck2>;
@@ -542,12 +556,34 @@ &wdog1 {
};

&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mclk>, <&pinctrl_camera_reset>;
+
pinctrl_buck2: vddarmgrp {
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x19
>;
};

+ pinctrl_camera1_pwdn: camera1pwdngrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19
+ >;
+ };
+
+ pinctrl_camera2_pwdn: camera2pwdngrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO05_GPIO1_IO5 0x19
+ >;
+ };
+
+ /* Shared reset line for cameras on CSI1 and CSI2. */
+ pinctrl_camera_reset: cameraresetgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19
+ >;
+ };
+
pinctrl_fec1: fec1grp {
fsl,pins = <
MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
@@ -575,12 +611,26 @@ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
>;
};

+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
+ >;
+ };
+
pinctrl_ir: irgrp {
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x4f
>;
};

+ /* Shared MCLK for cameras on CSI1 and CSI2. */
+ pinctrl_mclk: mclkgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO15_CCMSRCGPCMIX_CLKO2 0x59
+ >;
+ };
+
pinctrl_mipi_dsi: mipidsigrp {
fsl,pins = <
MX8MQ_IOMUXC_ECSPI1_SCLK_GPIO5_IO6 0x16
--
2.50.1